home *** CD-ROM | disk | FTP | other *** search
/ Mac Easy 2010 May / Mac Life Ubuntu.iso / casper / filesystem.squashfs / usr / share / perl / 5.10.0 / Module / Build / Base.pm < prev    next >
Encoding:
Perl POD Document  |  2009-06-26  |  118.4 KB  |  4,287 lines

  1. package Module::Build::Base;
  2.  
  3. use strict;
  4. use vars qw($VERSION);
  5. $VERSION = '0.2808_01';
  6. $VERSION = eval $VERSION;
  7. BEGIN { require 5.00503 }
  8.  
  9. use Carp;
  10. use File::Copy ();
  11. use File::Find ();
  12. use File::Path ();
  13. use File::Basename ();
  14. use File::Spec 0.82 ();
  15. use File::Compare ();
  16. use Module::Build::Dumper ();
  17. use IO::File ();
  18. use Text::ParseWords ();
  19.  
  20. use Module::Build::ModuleInfo;
  21. use Module::Build::Notes;
  22. use Module::Build::Config;
  23.  
  24.  
  25. #################### Constructors ###########################
  26. sub new {
  27.   my $self = shift()->_construct(@_);
  28.  
  29.   $self->{invoked_action} = $self->{action} ||= 'Build_PL';
  30.   $self->cull_args(@ARGV);
  31.   
  32.   die "Too early to specify a build action '$self->{action}'.  Do 'Build $self->{action}' instead.\n"
  33.     if $self->{action} && $self->{action} ne 'Build_PL';
  34.  
  35.   $self->check_manifest;
  36.   $self->check_prereq;
  37.   $self->check_autofeatures;
  38.  
  39.   $self->dist_name;
  40.   $self->dist_version;
  41.  
  42.   $self->_set_install_paths;
  43.   $self->_find_nested_builds;
  44.  
  45.   return $self;
  46. }
  47.  
  48. sub resume {
  49.   my $package = shift;
  50.   my $self = $package->_construct(@_);
  51.   $self->read_config;
  52.  
  53.   # If someone called Module::Build->current() or
  54.   # Module::Build->new_from_context() and the correct class to use is
  55.   # actually a *subclass* of Module::Build, we may need to load that
  56.   # subclass here and re-delegate the resume() method to it.
  57.   unless ( UNIVERSAL::isa($package, $self->build_class) ) {
  58.     my $build_class = $self->build_class;
  59.     my $config_dir = $self->config_dir || '_build';
  60.     my $build_lib = File::Spec->catdir( $config_dir, 'lib' );
  61.     unshift( @INC, $build_lib );
  62.     unless ( $build_class->can('new') ) {
  63.       eval "require $build_class; 1" or die "Failed to re-load '$build_class': $@";
  64.     }
  65.     return $build_class->resume(@_);
  66.   }
  67.  
  68.   unless ($self->_perl_is_same($self->{properties}{perl})) {
  69.     my $perl = $self->find_perl_interpreter;
  70.     $self->log_warn(" * WARNING: Configuration was initially created with '$self->{properties}{perl}',\n".
  71.             "   but we are now using '$perl'.\n");
  72.   }
  73.   
  74.   $self->cull_args(@ARGV);
  75.  
  76.   unless ($self->allow_mb_mismatch) {
  77.     my $mb_version = $Module::Build::VERSION;
  78.     die(" * ERROR: Configuration was initially created with Module::Build version '$self->{properties}{mb_version}',\n".
  79.     "   but we are now using version '$mb_version'.  Please re-run the Build.PL or Makefile.PL script,\n".
  80.     "   or use --allow_mb_mismatch 1 to skip this version check.\n")
  81.     if $mb_version ne $self->{properties}{mb_version};
  82.   }
  83.   
  84.   $self->{invoked_action} = $self->{action} ||= 'build';
  85.   
  86.   return $self;
  87. }
  88.  
  89. sub new_from_context {
  90.   my ($package, %args) = @_;
  91.   
  92.   # XXX Read the META.yml and see whether we need to run the Build.PL?
  93.   
  94.   # Run the Build.PL.  We use do() rather than run_perl_script() so
  95.   # that it runs in this process rather than a subprocess, because we
  96.   # need to make sure that the environment is the same during Build.PL
  97.   # as it is during resume() (and thereafter).
  98.   {
  99.     local @ARGV = $package->unparse_args(\%args);
  100.     do './Build.PL';
  101.     die $@ if $@;
  102.   }
  103.   return $package->resume;
  104. }
  105.  
  106. sub current {
  107.   # hmm, wonder what the right thing to do here is
  108.   local @ARGV;
  109.   return shift()->resume;
  110. }
  111.  
  112. sub _construct {
  113.   my ($package, %input) = @_;
  114.  
  115.   my $args   = delete $input{args}   || {};
  116.   my $config = delete $input{config} || {};
  117.  
  118.   my $self = bless {
  119.             args => {%$args},
  120.             config => Module::Build::Config->new(values => $config),
  121.             properties => {
  122.                    base_dir        => $package->cwd,
  123.                    mb_version      => $Module::Build::VERSION,
  124.                    %input,
  125.                   },
  126.             phash => {},
  127.            }, $package;
  128.  
  129.   $self->_set_defaults;
  130.   my ($p, $ph) = ($self->{properties}, $self->{phash});
  131.  
  132.   foreach (qw(notes config_data features runtime_params cleanup auto_features)) {
  133.     my $file = File::Spec->catfile($self->config_dir, $_);
  134.     $ph->{$_} = Module::Build::Notes->new(file => $file);
  135.     $ph->{$_}->restore if -e $file;
  136.     if (exists $p->{$_}) {
  137.       my $vals = delete $p->{$_};
  138.       while (my ($k, $v) = each %$vals) {
  139.     $self->$_($k, $v);
  140.       }
  141.     }
  142.   }
  143.  
  144.   # The following warning could be unnecessary if the user is running
  145.   # an embedded perl, but there aren't too many of those around, and
  146.   # embedded perls aren't usually used to install modules, and the
  147.   # installation process sometimes needs to run external scripts
  148.   # (e.g. to run tests).
  149.   $p->{perl} = $self->find_perl_interpreter
  150.     or $self->log_warn("Warning: Can't locate your perl binary");
  151.  
  152.   my $blibdir = sub { File::Spec->catdir($p->{blib}, @_) };
  153.   $p->{bindoc_dirs} ||= [ $blibdir->("script") ];
  154.   $p->{libdoc_dirs} ||= [ $blibdir->("lib"), $blibdir->("arch") ];
  155.  
  156.   $p->{dist_author} = [ $p->{dist_author} ] if defined $p->{dist_author} and not ref $p->{dist_author};
  157.  
  158.   # Synonyms
  159.   $p->{requires} = delete $p->{prereq} if defined $p->{prereq};
  160.   $p->{script_files} = delete $p->{scripts} if defined $p->{scripts};
  161.  
  162.   # Convert to arrays
  163.   for ('extra_compiler_flags', 'extra_linker_flags') {
  164.     $p->{$_} = [ $self->split_like_shell($p->{$_}) ] if exists $p->{$_};
  165.   }
  166.  
  167.   $self->add_to_cleanup( @{delete $p->{add_to_cleanup}} )
  168.     if $p->{add_to_cleanup};
  169.  
  170.   return $self;
  171. }
  172.  
  173. ################## End constructors #########################
  174.  
  175. sub log_info { print @_ unless shift()->quiet }
  176. sub log_verbose { shift()->log_info(@_) if $_[0]->verbose }
  177. sub log_warn {
  178.   # Try to make our call stack invisible
  179.   shift;
  180.   if (@_ and $_[-1] !~ /\n$/) {
  181.     my (undef, $file, $line) = caller();
  182.     warn @_, " at $file line $line.\n";
  183.   } else {
  184.     warn @_;
  185.   }
  186. }
  187.  
  188.  
  189. sub _set_install_paths {
  190.   my $self = shift;
  191.   my $c = $self->{config};
  192.   my $p = $self->{properties};
  193.  
  194.   my @libstyle = $c->get('installstyle') ?
  195.       File::Spec->splitdir($c->get('installstyle')) : qw(lib perl5);
  196.   my $arch     = $c->get('archname');
  197.   my $version  = $c->get('version');
  198.  
  199.   my $bindoc  = $c->get('installman1dir') || undef;
  200.   my $libdoc  = $c->get('installman3dir') || undef;
  201.  
  202.   my $binhtml = $c->get('installhtml1dir') || $c->get('installhtmldir') || undef;
  203.   my $libhtml = $c->get('installhtml3dir') || $c->get('installhtmldir') || undef;
  204.  
  205.   $p->{install_sets} =
  206.     {
  207.      core   => {
  208.         lib     => $c->get('installprivlib'),
  209.         arch    => $c->get('installarchlib'),
  210.         bin     => $c->get('installbin'),
  211.         script  => $c->get('installscript'),
  212.         bindoc  => $bindoc,
  213.         libdoc  => $libdoc,
  214.         binhtml => $binhtml,
  215.         libhtml => $libhtml,
  216.            },
  217.      site   => {
  218.         lib     => $c->get('installsitelib'),
  219.         arch    => $c->get('installsitearch'),
  220.         bin     => $c->get('installsitebin') || $c->get('installbin'),
  221.         script  => $c->get('installsitescript') ||
  222.                    $c->get('installsitebin') || $c->get('installscript'),
  223.         bindoc  => $c->get('installsiteman1dir') || $bindoc,
  224.         libdoc  => $c->get('installsiteman3dir') || $libdoc,
  225.         binhtml => $c->get('installsitehtml1dir') || $binhtml,
  226.         libhtml => $c->get('installsitehtml3dir') || $libhtml,
  227.            },
  228.      vendor => {
  229.         lib     => $c->get('installvendorlib'),
  230.         arch    => $c->get('installvendorarch'),
  231.         bin     => $c->get('installvendorbin') || $c->get('installbin'),
  232.         script  => $c->get('installvendorscript') ||
  233.                    $c->get('installvendorbin') || $c->get('installscript'),
  234.         bindoc  => $c->get('installvendorman1dir') || $bindoc,
  235.         libdoc  => $c->get('installvendorman3dir') || $libdoc,
  236.         binhtml => $c->get('installvendorhtml1dir') || $binhtml,
  237.         libhtml => $c->get('installvendorhtml3dir') || $libhtml,
  238.            },
  239.     };
  240.  
  241.   $p->{original_prefix} =
  242.     {
  243.      core   => $c->get('installprefixexp') || $c->get('installprefix') ||
  244.                $c->get('prefixexp')        || $c->get('prefix') || '',
  245.      site   => $c->get('siteprefixexp'),
  246.      vendor => $c->get('usevendorprefix') ? $c->get('vendorprefixexp') : '',
  247.     };
  248.   $p->{original_prefix}{site} ||= $p->{original_prefix}{core};
  249.  
  250.   # Note: you might be tempted to use $Config{installstyle} here
  251.   # instead of hard-coding lib/perl5, but that's been considered and
  252.   # (at least for now) rejected.  `perldoc Config` has some wisdom
  253.   # about it.
  254.   $p->{install_base_relpaths} =
  255.     {
  256.      lib     => ['lib', 'perl5'],
  257.      arch    => ['lib', 'perl5', $arch],
  258.      bin     => ['bin'],
  259.      script  => ['bin'],
  260.      bindoc  => ['man', 'man1'],
  261.      libdoc  => ['man', 'man3'],
  262.      binhtml => ['html'],
  263.      libhtml => ['html'],
  264.     };
  265.  
  266.   $p->{prefix_relpaths} =
  267.     {
  268.      core => {
  269.           lib        => [@libstyle],
  270.           arch       => [@libstyle, $version, $arch],
  271.           bin        => ['bin'],
  272.           script     => ['bin'],
  273.           bindoc     => ['man', 'man1'],
  274.           libdoc     => ['man', 'man3'],
  275.           binhtml    => ['html'],
  276.           libhtml    => ['html'],
  277.          },
  278.      vendor => {
  279.         lib        => [@libstyle],
  280.         arch       => [@libstyle, $version, $arch],
  281.         bin        => ['bin'],
  282.         script     => ['bin'],
  283.         bindoc     => ['man', 'man1'],
  284.         libdoc     => ['man', 'man3'],
  285.         binhtml    => ['html'],
  286.         libhtml    => ['html'],
  287.            },
  288.      site => {
  289.           lib        => [@libstyle, 'site_perl'],
  290.           arch       => [@libstyle, 'site_perl', $version, $arch],
  291.           bin        => ['bin'],
  292.           script     => ['bin'],
  293.           bindoc     => ['man', 'man1'],
  294.           libdoc     => ['man', 'man3'],
  295.           binhtml    => ['html'],
  296.           libhtml    => ['html'],
  297.          },
  298.     };
  299.  
  300. }
  301.  
  302. sub _find_nested_builds {
  303.   my $self = shift;
  304.   my $r = $self->recurse_into or return;
  305.  
  306.   my ($file, @r);
  307.   if (!ref($r) && $r eq 'auto') {
  308.     local *DH;
  309.     opendir DH, $self->base_dir
  310.       or die "Can't scan directory " . $self->base_dir . " for nested builds: $!";
  311.     while (defined($file = readdir DH)) {
  312.       my $subdir = File::Spec->catdir( $self->base_dir, $file );
  313.       next unless -d $subdir;
  314.       push @r, $subdir if -e File::Spec->catfile( $subdir, 'Build.PL' );
  315.     }
  316.   }
  317.  
  318.   $self->recurse_into(\@r);
  319. }
  320.  
  321. sub cwd {
  322.   require Cwd;
  323.   return Cwd::cwd();
  324. }
  325.  
  326. sub _quote_args {
  327.   # Returns a string that can become [part of] a command line with
  328.   # proper quoting so that the subprocess sees this same list of args.
  329.   my ($self, @args) = @_;
  330.  
  331.   my $return_args = '';
  332.   my @quoted;
  333.  
  334.   for (@args) {
  335.     if ( /^[^\s*?!$<>;\\|'"\[\]\{\}]+$/ ) {
  336.       # Looks pretty safe
  337.       push @quoted, $_;
  338.     } else {
  339.       # XXX this will obviously have to improve - is there already a
  340.       # core module lying around that does proper quoting?
  341.       s/"/"'"'"/g;
  342.       push @quoted, qq("$_");
  343.     }
  344.   }
  345.  
  346.   return join " ", @quoted;
  347. }
  348.  
  349. sub _backticks {
  350.   my ($self, @cmd) = @_;
  351.   if ($self->have_forkpipe) {
  352.     local *FH;
  353.     my $pid = open *FH, "-|";
  354.     if ($pid) {
  355.       return wantarray ? <FH> : join '', <FH>;
  356.     } else {
  357.       die "Can't execute @cmd: $!\n" unless defined $pid;
  358.       exec { $cmd[0] } @cmd;
  359.     }
  360.   } else {
  361.     my $cmd = $self->_quote_args(@cmd);
  362.     return `$cmd`;
  363.   }
  364. }
  365.  
  366. sub have_forkpipe { 1 }
  367.  
  368. # Determine whether a given binary is the same as the perl
  369. # (configuration) that started this process.
  370. sub _perl_is_same {
  371.   my ($self, $perl) = @_;
  372.  
  373.   my @cmd = ($perl);
  374.  
  375.   # When run from the perl core, @INC will include the directories
  376.   # where perl is yet to be installed. We need to reference the
  377.   # absolute path within the source distribution where it can find
  378.   # it's Config.pm This also prevents us from picking up a Config.pm
  379.   # from a different configuration that happens to be already
  380.   # installed in @INC.
  381.   if ($ENV{PERL_CORE}) {
  382.     push @cmd, '-I' . File::Spec->catdir(File::Basename::dirname($perl), 'lib');
  383.   }
  384.  
  385.   push @cmd, qw(-MConfig=myconfig -e print -e myconfig);
  386.   return $self->_backticks(@cmd) eq Config->myconfig;
  387. }
  388.  
  389. # cache _discover_perl_interpreter() results
  390. {
  391.   my $known_perl;
  392.   sub find_perl_interpreter {
  393.     my $self = shift;
  394.  
  395.     return $known_perl if defined($known_perl);
  396.     return $known_perl = $self->_discover_perl_interpreter;
  397.   }
  398. }
  399.  
  400. # Returns the absolute path of the perl interperter used to invoke
  401. # this process. The path is derived from $^X or $Config{perlpath}. On
  402. # some platforms $^X contains the complete absolute path of the
  403. # interpreter, on other it may contain a relative path, or simply
  404. # 'perl'. This can also vary depending on whether a path was supplied
  405. # when perl was invoked. Additionally, the value in $^X may omit the
  406. # executable extension on platforms that use one. It's a fatal error
  407. # if the interpreter can't be found because it can result in undefined
  408. # behavior by routines that depend on it (generating errors or
  409. # invoking the wrong perl.)
  410. sub _discover_perl_interpreter {
  411.   my $proto = shift;
  412.   my $c     = ref($proto) ? $proto->{config} : 'Module::Build::Config';
  413.  
  414.   my $perl  = $^X;
  415.   my $perl_basename = File::Basename::basename($perl);
  416.  
  417.   my @potential_perls;
  418.  
  419.   # Try 1, Check $^X for absolute path
  420.   push( @potential_perls, $perl )
  421.       if File::Spec->file_name_is_absolute($perl);
  422.  
  423.   # Try 2, Check $^X for a valid relative path
  424.   my $abs_perl = File::Spec->rel2abs($perl);
  425.   push( @potential_perls, $abs_perl );
  426.  
  427.   # Try 3, Last ditch effort: These two option use hackery to try to locate
  428.   # a suitable perl. The hack varies depending on whether we are running
  429.   # from an installed perl or an uninstalled perl in the perl source dist.
  430.   if ($ENV{PERL_CORE}) {
  431.  
  432.     # Try 3.A, If we are in a perl source tree, running an uninstalled
  433.     # perl, we can keep moving up the directory tree until we find our
  434.     # binary. We wouldn't do this under any other circumstances.
  435.  
  436.     # CBuilder is also in the core, so it should be available here
  437.     require ExtUtils::CBuilder;
  438.     my $perl_src = ExtUtils::CBuilder->perl_src;
  439.     if ( defined($perl_src) && length($perl_src) ) {
  440.       my $uninstperl =
  441.         File::Spec->rel2abs(File::Spec->catfile( $perl_src, $perl_basename ));
  442.       push( @potential_perls, $uninstperl );
  443.     }
  444.  
  445.   } else {
  446.  
  447.     # Try 3.B, First look in $Config{perlpath}, then search the user's
  448.     # PATH. We do not want to do either if we are running from an
  449.     # uninstalled perl in a perl source tree.
  450.  
  451.     push( @potential_perls, $c->get('perlpath') );
  452.  
  453.     push( @potential_perls,
  454.           map File::Spec->catfile($_, $perl_basename), File::Spec->path() );
  455.   }
  456.  
  457.   # Now that we've enumerated the potential perls, it's time to test
  458.   # them to see if any of them match our configuration, returning the
  459.   # absolute path of the first successful match.
  460.   my $exe = $c->get('exe_ext');
  461.   foreach my $thisperl ( @potential_perls ) {
  462.  
  463.     if (defined $exe) {
  464.       $thisperl .= $exe unless $thisperl =~ m/$exe$/i;
  465.     }
  466.  
  467.     if ( -f $thisperl && $proto->_perl_is_same($thisperl) ) {
  468.       return $thisperl;
  469.     }
  470.   }
  471.  
  472.   # We've tried all alternatives, and didn't find a perl that matches
  473.   # our configuration. Throw an exception, and list alternatives we tried.
  474.   my @paths = map File::Basename::dirname($_), @potential_perls;
  475.   die "Can't locate the perl binary used to run this script " .
  476.       "in (@paths)\n";
  477. }
  478.  
  479. sub _is_interactive {
  480.   return -t STDIN && (-t STDOUT || !(-f STDOUT || -c STDOUT)) ;   # Pipe?
  481. }
  482.  
  483. # NOTE this is a blocking operation if(-t STDIN)
  484. sub _is_unattended {
  485.   my $self = shift;
  486.   return $ENV{PERL_MM_USE_DEFAULT} ||
  487.     ( !$self->_is_interactive && eof STDIN );
  488. }
  489.  
  490. sub _readline {
  491.   my $self = shift;
  492.   return undef if $self->_is_unattended;
  493.  
  494.   my $answer = <STDIN>;
  495.   chomp $answer if defined $answer;
  496.   return $answer;
  497. }
  498.  
  499. sub prompt {
  500.   my $self = shift;
  501.   my $mess = shift
  502.     or die "prompt() called without a prompt message";
  503.  
  504.   # use a list to distinguish a default of undef() from no default
  505.   my @def;
  506.   @def = (shift) if @_;
  507.   # use dispdef for output
  508.   my @dispdef = scalar(@def) ?
  509.     ('[', (defined($def[0]) ? $def[0] . ' ' : ''), ']') :
  510.     (' ', '');
  511.  
  512.   local $|=1;
  513.   print "$mess ", @dispdef;
  514.  
  515.   if ( $self->_is_unattended && !@def ) {
  516.     die <<EOF;
  517. ERROR: This build seems to be unattended, but there is no default value
  518. for this question.  Aborting.
  519. EOF
  520.   }
  521.  
  522.   my $ans = $self->_readline();
  523.  
  524.   if ( !defined($ans)        # Ctrl-D or unattended
  525.        or !length($ans) ) {  # User hit return
  526.     print "$dispdef[1]\n";
  527.     $ans = scalar(@def) ? $def[0] : '';
  528.   }
  529.  
  530.   return $ans;
  531. }
  532.  
  533. sub y_n {
  534.   my $self = shift;
  535.   my ($mess, $def)  = @_;
  536.  
  537.   die "y_n() called without a prompt message" unless $mess;
  538.   die "Invalid default value: y_n() default must be 'y' or 'n'"
  539.     if $def && $def !~ /^[yn]/i;
  540.  
  541.   my $answer;
  542.   while (1) { # XXX Infinite or a large number followed by an exception ?
  543.     $answer = $self->prompt(@_);
  544.     return 1 if $answer =~ /^y/i;
  545.     return 0 if $answer =~ /^n/i;
  546.     local $|=1;
  547.     print "Please answer 'y' or 'n'.\n";
  548.   }
  549. }
  550.  
  551. sub current_action { shift->{action} }
  552. sub invoked_action { shift->{invoked_action} }
  553.  
  554. sub notes        { shift()->{phash}{notes}->access(@_) }
  555. sub config_data  { shift()->{phash}{config_data}->access(@_) }
  556. sub runtime_params { shift->{phash}{runtime_params}->read( @_ ? shift : () ) }  # Read-only
  557. sub auto_features  { shift()->{phash}{auto_features}->access(@_) }
  558.  
  559. sub features     {
  560.   my $self = shift;
  561.   my $ph = $self->{phash};
  562.  
  563.   if (@_) {
  564.     my $key = shift;
  565.     if ($ph->{features}->exists($key)) {
  566.       return $ph->{features}->access($key, @_);
  567.     }
  568.  
  569.     if (my $info = $ph->{auto_features}->access($key)) {
  570.       my $failures = $self->prereq_failures($info);
  571.       my $disabled = grep( /^(?:\w+_)?(?:requires|conflicts)$/,
  572.                keys %$failures ) ? 1 : 0;
  573.       return !$disabled;
  574.     }
  575.  
  576.     return $ph->{features}->access($key, @_);
  577.   }
  578.  
  579.   # No args - get the auto_features & overlay the regular features
  580.   my %features;
  581.   my %auto_features = $ph->{auto_features}->access();
  582.   while (my ($name, $info) = each %auto_features) {
  583.     my $failures = $self->prereq_failures($info);
  584.     my $disabled = grep( /^(?:\w+_)?(?:requires|conflicts)$/,
  585.              keys %$failures ) ? 1 : 0;
  586.     $features{$name} = $disabled ? 0 : 1;
  587.   }
  588.   %features = (%features, $ph->{features}->access());
  589.  
  590.   return wantarray ? %features : \%features;
  591. }
  592. BEGIN { *feature = \&features } # Alias
  593.  
  594. sub _mb_feature {
  595.   my $self = shift;
  596.   
  597.   if (($self->module_name || '') eq 'Module::Build') {
  598.     # We're building Module::Build itself, so ...::ConfigData isn't
  599.     # valid, but $self->features() should be.
  600.     return $self->feature(@_);
  601.   } else {
  602.     require Module::Build::ConfigData;
  603.     return Module::Build::ConfigData->feature(@_);
  604.   }
  605. }
  606.  
  607.  
  608. sub add_build_element {
  609.     my ($self, $elem) = @_;
  610.     my $elems = $self->build_elements;
  611.     push @$elems, $elem unless grep { $_ eq $elem } @$elems;
  612. }
  613.  
  614. sub ACTION_config_data {
  615.   my $self = shift;
  616.   return unless $self->has_config_data;
  617.   
  618.   my $module_name = $self->module_name
  619.     or die "The config_data feature requires that 'module_name' be set";
  620.   my $notes_name = $module_name . '::ConfigData'; # TODO: Customize name ???
  621.   my $notes_pm = File::Spec->catfile($self->blib, 'lib', split /::/, "$notes_name.pm");
  622.  
  623.   return if $self->up_to_date(['Build.PL',
  624.                    $self->config_file('config_data'),
  625.                    $self->config_file('features')
  626.                   ], $notes_pm);
  627.  
  628.   $self->log_info("Writing config notes to $notes_pm\n");
  629.   File::Path::mkpath(File::Basename::dirname($notes_pm));
  630.  
  631.   Module::Build::Notes->write_config_data
  632.       (
  633.        file => $notes_pm,
  634.        module => $module_name,
  635.        config_module => $notes_name,
  636.        config_data => scalar $self->config_data,
  637.        feature => scalar $self->{phash}{features}->access(),
  638.        auto_features => scalar $self->auto_features,
  639.       );
  640. }
  641.  
  642. {
  643.     my %valid_properties = ( __PACKAGE__,  {} );
  644.     my %additive_properties;
  645.  
  646.     sub _mb_classes {
  647.       my $class = ref($_[0]) || $_[0];
  648.       return ($class, $class->mb_parents);
  649.     }
  650.  
  651.     sub valid_property {
  652.       my ($class, $prop) = @_;
  653.       return grep exists( $valid_properties{$_}{$prop} ), $class->_mb_classes;
  654.     }
  655.  
  656.     sub valid_properties {
  657.       return keys %{ shift->valid_properties_defaults() };
  658.     }
  659.  
  660.     sub valid_properties_defaults {
  661.       my %out;
  662.       for (reverse shift->_mb_classes) {
  663.     @out{ keys %{ $valid_properties{$_} } } = values %{ $valid_properties{$_} };
  664.       }
  665.       return \%out;
  666.     }
  667.  
  668.     sub array_properties {
  669.       for (shift->_mb_classes) {
  670.         return @{$additive_properties{$_}->{ARRAY}}
  671.       if exists $additive_properties{$_}->{ARRAY};
  672.       }
  673.     }
  674.  
  675.     sub hash_properties {
  676.       for (shift->_mb_classes) {
  677.         return @{$additive_properties{$_}->{'HASH'}}
  678.       if exists $additive_properties{$_}->{'HASH'};
  679.       }
  680.     }
  681.  
  682.     sub add_property {
  683.       my ($class, $property, $default) = @_;
  684.       die "Property '$property' already exists" if $class->valid_property($property);
  685.  
  686.       $valid_properties{$class}{$property} = $default;
  687.  
  688.       my $type = ref $default;
  689.       if ($type) {
  690.     push @{$additive_properties{$class}->{$type}}, $property;
  691.       }
  692.  
  693.       unless ($class->can($property)) {
  694.         no strict 'refs';
  695.     if ( $type eq 'HASH' ) {
  696.           *{"$class\::$property"} = sub {
  697.         my $self = shift;
  698.         my $x = $self->{properties};
  699.         return $x->{$property} unless @_;
  700.  
  701.         if ( defined($_[0]) && !ref($_[0]) ) {
  702.           if ( @_ == 1 ) {
  703.         return exists( $x->{$property}{$_[0]} ) ?
  704.                  $x->{$property}{$_[0]} : undef;
  705.               } elsif ( @_ % 2 == 0 ) {
  706.             my %args = @_;
  707.             while ( my($k, $v) = each %args ) {
  708.               $x->{$property}{$k} = $v;
  709.             }
  710.           } else {
  711.         die "Unexpected arguments for property '$property'\n";
  712.           }
  713.         } else {
  714.           $x->{$property} = $_[0];
  715.         }
  716.       };
  717.  
  718.         } else {
  719.           *{"$class\::$property"} = sub {
  720.         my $self = shift;
  721.         $self->{properties}{$property} = shift if @_;
  722.         return $self->{properties}{$property};
  723.       }
  724.         }
  725.  
  726.       }
  727.       return $class;
  728.     }
  729.  
  730.     sub _set_defaults {
  731.       my $self = shift;
  732.  
  733.       # Set the build class.
  734.       $self->{properties}{build_class} ||= ref $self;
  735.  
  736.       # If there was no orig_dir, set to the same as base_dir
  737.       $self->{properties}{orig_dir} ||= $self->{properties}{base_dir};
  738.  
  739.       my $defaults = $self->valid_properties_defaults;
  740.       
  741.       foreach my $prop (keys %$defaults) {
  742.     $self->{properties}{$prop} = $defaults->{$prop}
  743.       unless exists $self->{properties}{$prop};
  744.       }
  745.       
  746.       # Copy defaults for arrays any arrays.
  747.       for my $prop ($self->array_properties) {
  748.     $self->{properties}{$prop} = [@{$defaults->{$prop}}]
  749.       unless exists $self->{properties}{$prop};
  750.       }
  751.       # Copy defaults for arrays any hashes.
  752.       for my $prop ($self->hash_properties) {
  753.     $self->{properties}{$prop} = {%{$defaults->{$prop}}}
  754.       unless exists $self->{properties}{$prop};
  755.       }
  756.     }
  757.  
  758. }
  759.  
  760. # Add the default properties.
  761. __PACKAGE__->add_property(blib => 'blib');
  762. __PACKAGE__->add_property(build_class => 'Module::Build');
  763. __PACKAGE__->add_property(build_elements => [qw(PL support pm xs pod script)]);
  764. __PACKAGE__->add_property(build_script => 'Build');
  765. __PACKAGE__->add_property(build_bat => 0);
  766. __PACKAGE__->add_property(config_dir => '_build');
  767. __PACKAGE__->add_property(include_dirs => []);
  768. __PACKAGE__->add_property(installdirs => 'site');
  769. __PACKAGE__->add_property(metafile => 'META.yml');
  770. __PACKAGE__->add_property(recurse_into => []);
  771. __PACKAGE__->add_property(use_rcfile => 1);
  772. __PACKAGE__->add_property(create_packlist => 1);
  773. __PACKAGE__->add_property(allow_mb_mismatch => 0);
  774. __PACKAGE__->add_property(config => undef);
  775.  
  776. {
  777.   my $Is_ActivePerl = eval {require ActivePerl::DocTools};
  778.   __PACKAGE__->add_property(html_css => $Is_ActivePerl ? 'Active.css' : '');
  779. }
  780.  
  781. {
  782.   my @prereq_action_types = qw(requires build_requires conflicts recommends);
  783.   foreach my $type (@prereq_action_types) {
  784.     __PACKAGE__->add_property($type => {});
  785.   }
  786.   __PACKAGE__->add_property(prereq_action_types => \@prereq_action_types);
  787. }
  788.  
  789. __PACKAGE__->add_property($_ => {}) for qw(
  790.   get_options
  791.   install_base_relpaths
  792.   install_path
  793.   install_sets
  794.   meta_add
  795.   meta_merge
  796.   original_prefix
  797.   prefix_relpaths
  798.   configure_requires
  799. );
  800.  
  801. __PACKAGE__->add_property($_) for qw(
  802.   PL_files
  803.   autosplit
  804.   base_dir
  805.   bindoc_dirs
  806.   c_source
  807.   create_makefile_pl
  808.   create_readme
  809.   debugger
  810.   destdir
  811.   dist_abstract
  812.   dist_author
  813.   dist_name
  814.   dist_version
  815.   dist_version_from
  816.   extra_compiler_flags
  817.   extra_linker_flags
  818.   has_config_data
  819.   install_base
  820.   libdoc_dirs
  821.   license
  822.   magic_number
  823.   mb_version
  824.   module_name
  825.   orig_dir
  826.   perl
  827.   pm_files
  828.   pod_files
  829.   pollute
  830.   prefix
  831.   quiet
  832.   recursive_test_files
  833.   script_files
  834.   scripts
  835.   test_files
  836.   verbose
  837.   xs_files
  838. );
  839.  
  840. sub config {
  841.   my $self = shift;
  842.   my $c = ref($self) ? $self->{config} : 'Module::Build::Config';
  843.   return $c->all_config unless @_;
  844.  
  845.   my $key = shift;
  846.   return $c->get($key) unless @_;
  847.  
  848.   my $val = shift;
  849.   return $c->set($key => $val);
  850. }
  851.  
  852. sub mb_parents {
  853.     # Code borrowed from Class::ISA.
  854.     my @in_stack = (shift);
  855.     my %seen = ($in_stack[0] => 1);
  856.  
  857.     my ($current, @out);
  858.     while (@in_stack) {
  859.         next unless defined($current = shift @in_stack)
  860.           && $current->isa('Module::Build::Base');
  861.         push @out, $current;
  862.         next if $current eq 'Module::Build::Base';
  863.         no strict 'refs';
  864.         unshift @in_stack,
  865.           map {
  866.               my $c = $_; # copy, to avoid being destructive
  867.               substr($c,0,2) = "main::" if substr($c,0,2) eq '::';
  868.               # Canonize the :: -> main::, ::foo -> main::foo thing.
  869.               # Should I ever canonize the Foo'Bar = Foo::Bar thing?
  870.               $seen{$c}++ ? () : $c;
  871.           } @{"$current\::ISA"};
  872.  
  873.         # I.e., if this class has any parents (at least, ones I've never seen
  874.         # before), push them, in order, onto the stack of classes I need to
  875.         # explore.
  876.     }
  877.     shift @out;
  878.     return @out;
  879. }
  880.  
  881. sub extra_linker_flags   { shift->_list_accessor('extra_linker_flags',   @_) }
  882. sub extra_compiler_flags { shift->_list_accessor('extra_compiler_flags', @_) }
  883.  
  884. sub _list_accessor {
  885.   (my $self, local $_) = (shift, shift);
  886.   my $p = $self->{properties};
  887.   $p->{$_} = [@_] if @_;
  888.   $p->{$_} = [] unless exists $p->{$_};
  889.   return ref($p->{$_}) ? $p->{$_} : [$p->{$_}];
  890. }
  891.  
  892. # XXX Problem - if Module::Build is loaded from a different directory,
  893. # it'll look for (and perhaps destroy/create) a _build directory.
  894. sub subclass {
  895.   my ($pack, %opts) = @_;
  896.  
  897.   my $build_dir = '_build'; # XXX The _build directory is ostensibly settable by the user.  Shouldn't hard-code here.
  898.   $pack->delete_filetree($build_dir) if -e $build_dir;
  899.  
  900.   die "Must provide 'code' or 'class' option to subclass()\n"
  901.     unless $opts{code} or $opts{class};
  902.  
  903.   $opts{code}  ||= '';
  904.   $opts{class} ||= 'MyModuleBuilder';
  905.   
  906.   my $filename = File::Spec->catfile($build_dir, 'lib', split '::', $opts{class}) . '.pm';
  907.   my $filedir  = File::Basename::dirname($filename);
  908.   $pack->log_info("Creating custom builder $filename in $filedir\n");
  909.   
  910.   File::Path::mkpath($filedir);
  911.   die "Can't create directory $filedir: $!" unless -d $filedir;
  912.   
  913.   my $fh = IO::File->new("> $filename") or die "Can't create $filename: $!";
  914.   print $fh <<EOF;
  915. package $opts{class};
  916. use $pack;
  917. \@ISA = qw($pack);
  918. $opts{code}
  919. 1;
  920. EOF
  921.   close $fh;
  922.   
  923.   unshift @INC, File::Spec->catdir(File::Spec->rel2abs($build_dir), 'lib');
  924.   eval "use $opts{class}";
  925.   die $@ if $@;
  926.  
  927.   return $opts{class};
  928. }
  929.  
  930. sub dist_name {
  931.   my $self = shift;
  932.   my $p = $self->{properties};
  933.   return $p->{dist_name} if defined $p->{dist_name};
  934.   
  935.   die "Can't determine distribution name, must supply either 'dist_name' or 'module_name' parameter"
  936.     unless $self->module_name;
  937.   
  938.   ($p->{dist_name} = $self->module_name) =~ s/::/-/g;
  939.   
  940.   return $p->{dist_name};
  941. }
  942.  
  943. sub dist_version_from {
  944.   my ($self) = @_;
  945.   my $p = $self->{properties};
  946.   if ($self->module_name) {
  947.     $p->{dist_version_from} ||=
  948.     join( '/', 'lib', split(/::/, $self->module_name) ) . '.pm';
  949.   }
  950.   return $p->{dist_version_from} || undef;
  951. }
  952.  
  953. sub dist_version {
  954.   my ($self) = @_;
  955.   my $p = $self->{properties};
  956.  
  957.   return $p->{dist_version} if defined $p->{dist_version};
  958.  
  959.   if ( my $dist_version_from = $self->dist_version_from ) {
  960.     my $version_from = File::Spec->catfile( split( qr{/}, $dist_version_from ) );
  961.     my $pm_info = Module::Build::ModuleInfo->new_from_file( $version_from )
  962.       or die "Can't find file $version_from to determine version";
  963.     $p->{dist_version} = $pm_info->version();
  964.   }
  965.  
  966.   die ("Can't determine distribution version, must supply either 'dist_version',\n".
  967.        "'dist_version_from', or 'module_name' parameter")
  968.     unless defined $p->{dist_version};
  969.  
  970.   return $p->{dist_version};
  971. }
  972.  
  973. sub dist_author   { shift->_pod_parse('author')   }
  974. sub dist_abstract { shift->_pod_parse('abstract') }
  975.  
  976. sub _pod_parse {
  977.   my ($self, $part) = @_;
  978.   my $p = $self->{properties};
  979.   my $member = "dist_$part";
  980.   return $p->{$member} if defined $p->{$member};
  981.   
  982.   my $docfile = $self->_main_docfile
  983.     or return;
  984.   my $fh = IO::File->new($docfile)
  985.     or return;
  986.   
  987.   require Module::Build::PodParser;
  988.   my $parser = Module::Build::PodParser->new(fh => $fh);
  989.   my $method = "get_$part";
  990.   return $p->{$member} = $parser->$method();
  991. }
  992.  
  993. sub version_from_file { # Method provided for backwards compatability
  994.   return Module::Build::ModuleInfo->new_from_file($_[1])->version();
  995. }
  996.  
  997. sub find_module_by_name { # Method provided for backwards compatability
  998.   return Module::Build::ModuleInfo->find_module_by_name(@_[1,2]);
  999. }
  1000.  
  1001. sub add_to_cleanup {
  1002.   my $self = shift;
  1003.   my %files = map {$self->localize_file_path($_), 1} @_;
  1004.   $self->{phash}{cleanup}->write(\%files);
  1005. }
  1006.  
  1007. sub cleanup {
  1008.   my $self = shift;
  1009.   my $all = $self->{phash}{cleanup}->read;
  1010.   return keys %$all;
  1011. }
  1012.  
  1013. sub config_file {
  1014.   my $self = shift;
  1015.   return unless -d $self->config_dir;
  1016.   return File::Spec->catfile($self->config_dir, @_);
  1017. }
  1018.  
  1019. sub read_config {
  1020.   my ($self) = @_;
  1021.   
  1022.   my $file = $self->config_file('build_params')
  1023.     or die "Can't find 'build_params' in " . $self->config_dir;
  1024.   my $fh = IO::File->new($file) or die "Can't read '$file': $!";
  1025.   my $ref = eval do {local $/; <$fh>};
  1026.   die if $@;
  1027.   my $c;
  1028.   ($self->{args}, $c, $self->{properties}) = @$ref;
  1029.   $self->{config} = Module::Build::Config->new(values => $c);
  1030.   close $fh;
  1031. }
  1032.  
  1033. sub has_config_data {
  1034.   my $self = shift;
  1035.   return scalar grep $self->{phash}{$_}->has_data(), qw(config_data features auto_features);
  1036. }
  1037.  
  1038. sub _write_data {
  1039.   my ($self, $filename, $data) = @_;
  1040.   
  1041.   my $file = $self->config_file($filename);
  1042.   my $fh = IO::File->new("> $file") or die "Can't create '$file': $!";
  1043.   unless (ref($data)) {  # e.g. magicnum
  1044.     print $fh $data;
  1045.     return;
  1046.   }
  1047.  
  1048.   print {$fh} Module::Build::Dumper->_data_dump($data);
  1049. }
  1050.  
  1051. sub write_config {
  1052.   my ($self) = @_;
  1053.   
  1054.   File::Path::mkpath($self->{properties}{config_dir});
  1055.   -d $self->{properties}{config_dir} or die "Can't mkdir $self->{properties}{config_dir}: $!";
  1056.   
  1057.   my @items = @{ $self->prereq_action_types };
  1058.   $self->_write_data('prereqs', { map { $_, $self->$_() } @items });
  1059.   $self->_write_data('build_params', [$self->{args}, $self->{config}->values_set, $self->{properties}]);
  1060.  
  1061.   # Set a new magic number and write it to a file
  1062.   $self->_write_data('magicnum', $self->magic_number(int rand 1_000_000));
  1063.  
  1064.   $self->{phash}{$_}->write() foreach qw(notes cleanup features auto_features config_data runtime_params);
  1065. }
  1066.  
  1067. sub check_autofeatures {
  1068.   my ($self) = @_;
  1069.   my $features = $self->auto_features;
  1070.   
  1071.   return unless %$features;
  1072.  
  1073.   $self->log_info("Checking features:\n");
  1074.  
  1075.   my $max_name_len;
  1076.   $max_name_len = ( length($_) > $max_name_len ) ?
  1077.                     length($_) : $max_name_len
  1078.     for keys %$features;
  1079.  
  1080.   while (my ($name, $info) = each %$features) {
  1081.     $self->log_info("  $name" . '.' x ($max_name_len - length($name) + 4));
  1082.  
  1083.     if ( my $failures = $self->prereq_failures($info) ) {
  1084.       my $disabled = grep( /^(?:\w+_)?(?:requires|conflicts)$/,
  1085.                keys %$failures ) ? 1 : 0;
  1086.       $self->log_info( $disabled ? "disabled\n" : "enabled\n" );
  1087.  
  1088.       my $log_text;
  1089.       while (my ($type, $prereqs) = each %$failures) {
  1090.     while (my ($module, $status) = each %$prereqs) {
  1091.       my $required =
  1092.         ($type =~ /^(?:\w+_)?(?:requires|conflicts)$/) ? 1 : 0;
  1093.       my $prefix = ($required) ? '-' : '*';
  1094.       $log_text .= "    $prefix $status->{message}\n";
  1095.     }
  1096.       }
  1097.       $self->log_warn("$log_text") unless $self->quiet;
  1098.     } else {
  1099.       $self->log_info("enabled\n");
  1100.     }
  1101.   }
  1102.  
  1103.   $self->log_warn("\n");
  1104. }
  1105.  
  1106. sub prereq_failures {
  1107.   my ($self, $info) = @_;
  1108.  
  1109.   my @types = @{ $self->prereq_action_types };
  1110.   $info ||= {map {$_, $self->$_()} @types};
  1111.  
  1112.   my $out;
  1113.  
  1114.   foreach my $type (@types) {
  1115.     my $prereqs = $info->{$type};
  1116.     while ( my ($modname, $spec) = each %$prereqs ) {
  1117.       my $status = $self->check_installed_status($modname, $spec);
  1118.  
  1119.       if ($type =~ /^(?:\w+_)?conflicts$/) {
  1120.     next if !$status->{ok};
  1121.     $status->{conflicts} = delete $status->{need};
  1122.     $status->{message} = "$modname ($status->{have}) conflicts with this distribution";
  1123.  
  1124.       } elsif ($type =~ /^(?:\w+_)?recommends$/) {
  1125.     next if $status->{ok};
  1126.     $status->{message} = (!ref($status->{have}) && $status->{have} eq '<none>'
  1127.                   ? "Optional prerequisite $modname is not installed"
  1128.                   : "$modname ($status->{have}) is installed, but we prefer to have $spec");
  1129.       } else {
  1130.     next if $status->{ok};
  1131.       }
  1132.  
  1133.       $out->{$type}{$modname} = $status;
  1134.     }
  1135.   }
  1136.  
  1137.   return $out;
  1138. }
  1139.  
  1140. # returns a hash of defined prerequisites; i.e. only prereq types with values
  1141. sub _enum_prereqs {
  1142.   my $self = shift;
  1143.   my %prereqs;
  1144.   foreach my $type ( @{ $self->prereq_action_types } ) {
  1145.     if ( $self->can( $type ) ) {
  1146.       my $prereq = $self->$type() || {};
  1147.       $prereqs{$type} = $prereq if %$prereq;
  1148.     }
  1149.   }
  1150.   return \%prereqs;
  1151. }
  1152.  
  1153. sub check_prereq {
  1154.   my $self = shift;
  1155.  
  1156.   # If we have XS files, make sure we can process them.
  1157.   my $xs_files = $self->find_xs_files;
  1158.   if (keys %$xs_files && !$self->_mb_feature('C_support')) {
  1159.     $self->log_warn("Warning: this distribution contains XS files, ".
  1160.             "but Module::Build is not configured with C_support.  ".
  1161.             "Please install ExtUtils::CBuilder to enable C_support.\n");
  1162.   }
  1163.  
  1164.   # Check to see if there are any prereqs to check
  1165.   my $info = $self->_enum_prereqs;
  1166.   return 1 unless $info;
  1167.  
  1168.   $self->log_info("Checking prerequisites...\n");
  1169.  
  1170.   my $failures = $self->prereq_failures($info);
  1171.  
  1172.   if ( $failures ) {
  1173.  
  1174.     while (my ($type, $prereqs) = each %$failures) {
  1175.       while (my ($module, $status) = each %$prereqs) {
  1176.     my $prefix = ($type =~ /^(?:\w+_)?recommends$/) ? '*' : '- ERROR:';
  1177.     $self->log_warn(" $prefix $status->{message}\n");
  1178.       }
  1179.     }
  1180.  
  1181.     $self->log_warn(<<EOF);
  1182.  
  1183. ERRORS/WARNINGS FOUND IN PREREQUISITES.  You may wish to install the versions
  1184. of the modules indicated above before proceeding with this installation
  1185.  
  1186. EOF
  1187.     return 0;
  1188.  
  1189.   } else {
  1190.  
  1191.     $self->log_info("Looks good\n\n");
  1192.     return 1;
  1193.  
  1194.   }
  1195. }
  1196.  
  1197. sub perl_version {
  1198.   my ($self) = @_;
  1199.   # Check the current perl interpreter
  1200.   # It's much more convenient to use $] here than $^V, but 'man
  1201.   # perlvar' says I'm not supposed to.  Bloody tyrant.
  1202.   return $^V ? $self->perl_version_to_float(sprintf "%vd", $^V) : $];
  1203. }
  1204.  
  1205. sub perl_version_to_float {
  1206.   my ($self, $version) = @_;
  1207.   return $version if grep( /\./, $version ) < 2;
  1208.   $version =~ s/\./../;
  1209.   $version =~ s/\.(\d+)/sprintf '%03d', $1/eg;
  1210.   return $version;
  1211. }
  1212.  
  1213. sub _parse_conditions {
  1214.   my ($self, $spec) = @_;
  1215.  
  1216.   if ($spec =~ /^\s*([\w.]+)\s*$/) { # A plain number, maybe with dots, letters, and underscores
  1217.     return (">= $spec");
  1218.   } else {
  1219.     return split /\s*,\s*/, $spec;
  1220.   }
  1221. }
  1222.  
  1223. sub check_installed_status {
  1224.   my ($self, $modname, $spec) = @_;
  1225.   my %status = (need => $spec);
  1226.   
  1227.   if ($modname eq 'perl') {
  1228.     $status{have} = $self->perl_version;
  1229.   
  1230.   } elsif (eval { no strict; $status{have} = ${"${modname}::VERSION"} }) {
  1231.     # Don't try to load if it's already loaded
  1232.     
  1233.   } else {
  1234.     my $pm_info = Module::Build::ModuleInfo->new_from_module( $modname );
  1235.     unless (defined( $pm_info )) {
  1236.       @status{ qw(have message) } = ('<none>', "$modname is not installed");
  1237.       return \%status;
  1238.     }
  1239.     
  1240.     $status{have} = $pm_info->version();
  1241.     if ($spec and !defined($status{have})) {
  1242.       @status{ qw(have message) } = (undef, "Couldn't find a \$VERSION in prerequisite $modname");
  1243.       return \%status;
  1244.     }
  1245.   }
  1246.   
  1247.   my @conditions = $self->_parse_conditions($spec);
  1248.   
  1249.   foreach (@conditions) {
  1250.     my ($op, $version) = /^\s*  (<=?|>=?|==|!=)  \s*  ([\w.]+)  \s*$/x
  1251.       or die "Invalid prerequisite condition '$_' for $modname";
  1252.     
  1253.     $version = $self->perl_version_to_float($version)
  1254.       if $modname eq 'perl';
  1255.     
  1256.     next if $op eq '>=' and !$version;  # Module doesn't have to actually define a $VERSION
  1257.     
  1258.     unless ($self->compare_versions( $status{have}, $op, $version )) {
  1259.       $status{message} = "$modname ($status{have}) is installed, but we need version $op $version";
  1260.       return \%status;
  1261.     }
  1262.   }
  1263.   
  1264.   $status{ok} = 1;
  1265.   return \%status;
  1266. }
  1267.  
  1268. sub compare_versions {
  1269.   my $self = shift;
  1270.   my ($v1, $op, $v2) = @_;
  1271.   $v1 = Module::Build::Version->new($v1) 
  1272.     unless UNIVERSAL::isa($v1,'Module::Build::Version');
  1273.  
  1274.   my $eval_str = "\$v1 $op \$v2";
  1275.   my $result   = eval $eval_str;
  1276.   $self->log_warn("error comparing versions: '$eval_str' $@") if $@;
  1277.  
  1278.   return $result;
  1279. }
  1280.  
  1281. # I wish I could set $! to a string, but I can't, so I use $@
  1282. sub check_installed_version {
  1283.   my ($self, $modname, $spec) = @_;
  1284.   
  1285.   my $status = $self->check_installed_status($modname, $spec);
  1286.   
  1287.   if ($status->{ok}) {
  1288.     return $status->{have} if $status->{have} and $status->{have} ne '<none>';
  1289.     return '0 but true';
  1290.   }
  1291.   
  1292.   $@ = $status->{message};
  1293.   return 0;
  1294. }
  1295.  
  1296. sub make_executable {
  1297.   # Perl's chmod() is mapped to useful things on various non-Unix
  1298.   # platforms, so we use it in the base class even though it looks
  1299.   # Unixish.
  1300.  
  1301.   my $self = shift;
  1302.   foreach (@_) {
  1303.     my $current_mode = (stat $_)[2];
  1304.     chmod $current_mode | oct(111), $_;
  1305.   }
  1306. }
  1307.  
  1308. sub is_executable {
  1309.   # We assume this does the right thing on generic platforms, though
  1310.   # we do some other more specific stuff on Unixish platforms.
  1311.   my ($self, $file) = @_;
  1312.   return -x $file;
  1313. }
  1314.  
  1315. sub _startperl { shift()->config('startperl') }
  1316.  
  1317. # Return any directories in @INC which are not in the default @INC for
  1318. # this perl.  For example, stuff passed in with -I or loaded with "use lib".
  1319. sub _added_to_INC {
  1320.   my $self = shift;
  1321.  
  1322.   my %seen;
  1323.   $seen{$_}++ foreach $self->_default_INC;
  1324.   return grep !$seen{$_}++, @INC;
  1325. }
  1326.  
  1327. # Determine the default @INC for this Perl
  1328. {
  1329.   my @default_inc; # Memoize
  1330.   sub _default_INC {
  1331.     my $self = shift;
  1332.     return @default_inc if @default_inc;
  1333.     
  1334.     local $ENV{PERL5LIB};  # this is not considered part of the default.
  1335.     
  1336.     my $perl = ref($self) ? $self->perl : $self->find_perl_interpreter;
  1337.     
  1338.     my @inc = $self->_backticks($perl, '-le', 'print for @INC');
  1339.     chomp @inc;
  1340.     
  1341.     return @default_inc = @inc;
  1342.   }
  1343. }
  1344.  
  1345. sub print_build_script {
  1346.   my ($self, $fh) = @_;
  1347.   
  1348.   my $build_package = $self->build_class;
  1349.   
  1350.   my $closedata="";
  1351.  
  1352.   my %q = map {$_, $self->$_()} qw(config_dir base_dir);
  1353.  
  1354.   my $case_tolerant = 0+(File::Spec->can('case_tolerant')
  1355.              && File::Spec->case_tolerant);
  1356.   $q{base_dir} = uc $q{base_dir} if $case_tolerant;
  1357.   $q{base_dir} = Win32::GetShortPathName($q{base_dir}) if $self->is_windowsish;
  1358.  
  1359.   $q{magic_numfile} = $self->config_file('magicnum');
  1360.  
  1361.   my @myINC = $self->_added_to_INC;
  1362.   for (@myINC, values %q) {
  1363.     $_ = File::Spec->canonpath( $_ );
  1364.     s/([\\\'])/\\$1/g;
  1365.   }
  1366.  
  1367.   my $quoted_INC = join ",\n", map "     '$_'", @myINC;
  1368.   my $shebang = $self->_startperl;
  1369.   my $magic_number = $self->magic_number;
  1370.  
  1371.   print $fh <<EOF;
  1372. $shebang
  1373.  
  1374. use strict;
  1375. use Cwd;
  1376. use File::Basename;
  1377. use File::Spec;
  1378.  
  1379. sub magic_number_matches {
  1380.   return 0 unless -e '$q{magic_numfile}';
  1381.   local *FH;
  1382.   open FH, '$q{magic_numfile}' or return 0;
  1383.   my \$filenum = <FH>;
  1384.   close FH;
  1385.   return \$filenum == $magic_number;
  1386. }
  1387.  
  1388. my \$progname;
  1389. my \$orig_dir;
  1390. BEGIN {
  1391.   \$^W = 1;  # Use warnings
  1392.   \$progname = basename(\$0);
  1393.   \$orig_dir = Cwd::cwd();
  1394.   my \$base_dir = '$q{base_dir}';
  1395.   if (!magic_number_matches()) {
  1396.     unless (chdir(\$base_dir)) {
  1397.       die ("Couldn't chdir(\$base_dir), aborting\\n");
  1398.     }
  1399.     unless (magic_number_matches()) {
  1400.       die ("Configuration seems to be out of date, please re-run 'perl Build.PL' again.\\n");
  1401.     }
  1402.   }
  1403.   unshift \@INC,
  1404.     (
  1405. $quoted_INC
  1406.     );
  1407. }
  1408.  
  1409. close(*DATA) unless eof(*DATA); # ensure no open handles to this script
  1410.  
  1411. use $build_package;
  1412.  
  1413. # Some platforms have problems setting \$^X in shebang contexts, fix it up here
  1414. \$^X = Module::Build->find_perl_interpreter;
  1415.  
  1416. if (-e 'Build.PL' and not $build_package->up_to_date('Build.PL', \$progname)) {
  1417.    warn "Warning: Build.PL has been altered.  You may need to run 'perl Build.PL' again.\\n";
  1418. }
  1419.  
  1420. # This should have just enough arguments to be able to bootstrap the rest.
  1421. my \$build = $build_package->resume (
  1422.   properties => {
  1423.     config_dir => '$q{config_dir}',
  1424.     orig_dir => \$orig_dir,
  1425.   },
  1426. );
  1427.  
  1428. \$build->dispatch;
  1429. EOF
  1430. }
  1431.  
  1432. sub create_build_script {
  1433.   my ($self) = @_;
  1434.   $self->write_config;
  1435.   
  1436.   my ($build_script, $dist_name, $dist_version)
  1437.     = map $self->$_(), qw(build_script dist_name dist_version);
  1438.   
  1439.   if ( $self->delete_filetree($build_script) ) {
  1440.     $self->log_info("Removed previous script '$build_script'\n\n");
  1441.   }
  1442.  
  1443.   $self->log_info("Creating new '$build_script' script for ",
  1444.           "'$dist_name' version '$dist_version'\n");
  1445.   my $fh = IO::File->new(">$build_script") or die "Can't create '$build_script': $!";
  1446.   $self->print_build_script($fh);
  1447.   close $fh;
  1448.   
  1449.   $self->make_executable($build_script);
  1450.  
  1451.   return 1;
  1452. }
  1453.  
  1454. sub check_manifest {
  1455.   my $self = shift;
  1456.   return unless -e 'MANIFEST';
  1457.   
  1458.   # Stolen nearly verbatim from MakeMaker.  But ExtUtils::Manifest
  1459.   # could easily be re-written into a modern Perl dialect.
  1460.  
  1461.   require ExtUtils::Manifest;  # ExtUtils::Manifest is not warnings clean.
  1462.   local ($^W, $ExtUtils::Manifest::Quiet) = (0,1);
  1463.   
  1464.   $self->log_info("Checking whether your kit is complete...\n");
  1465.   if (my @missed = ExtUtils::Manifest::manicheck()) {
  1466.     $self->log_warn("WARNING: the following files are missing in your kit:\n",
  1467.             "\t", join("\n\t", @missed), "\n",
  1468.             "Please inform the author.\n\n");
  1469.   } else {
  1470.     $self->log_info("Looks good\n\n");
  1471.   }
  1472. }
  1473.  
  1474. sub dispatch {
  1475.   my $self = shift;
  1476.   local $self->{_completed_actions} = {};
  1477.  
  1478.   if (@_) {
  1479.     my ($action, %p) = @_;
  1480.     my $args = $p{args} ? delete($p{args}) : {};
  1481.  
  1482.     local $self->{invoked_action} = $action;
  1483.     local $self->{args} = {%{$self->{args}}, %$args};
  1484.     local $self->{properties} = {%{$self->{properties}}, %p};
  1485.     return $self->_call_action($action);
  1486.   }
  1487.  
  1488.   die "No build action specified" unless $self->{action};
  1489.   local $self->{invoked_action} = $self->{action};
  1490.   $self->_call_action($self->{action});
  1491. }
  1492.  
  1493. sub _call_action {
  1494.   my ($self, $action) = @_;
  1495.  
  1496.   return if $self->{_completed_actions}{$action}++;
  1497.  
  1498.   local $self->{action} = $action;
  1499.   my $method = "ACTION_$action";
  1500.   die "No action '$action' defined, try running the 'help' action.\n" unless $self->can($method);
  1501.   return $self->$method();
  1502. }
  1503.  
  1504. sub cull_options {
  1505.     my $self = shift;
  1506.     my $specs = $self->get_options or return ({}, @_);
  1507.     require Getopt::Long;
  1508.     # XXX Should we let Getopt::Long handle M::B's options? That would
  1509.     # be easy-ish to add to @specs right here, but wouldn't handle options
  1510.     # passed without "--" as M::B currently allows. We might be able to
  1511.     # get around this by setting the "prefix_pattern" Configure option.
  1512.     my @specs;
  1513.     my $args = {};
  1514.     # Construct the specifications for GetOptions.
  1515.     while (my ($k, $v) = each %$specs) {
  1516.         # Throw an error if specs conflict with our own.
  1517.         die "Option specification '$k' conflicts with a " . ref $self
  1518.           . " option of the same name"
  1519.           if $self->valid_property($k);
  1520.         push @specs, $k . (defined $v->{type} ? $v->{type} : '');
  1521.         push @specs, $v->{store} if exists $v->{store};
  1522.         $args->{$k} = $v->{default} if exists $v->{default};
  1523.     }
  1524.  
  1525.     local @ARGV = @_; # No other way to dupe Getopt::Long
  1526.  
  1527.     # Get the options values and return them.
  1528.     # XXX Add option to allow users to set options?
  1529.     if ( @specs ) {
  1530.       Getopt::Long::Configure('pass_through');
  1531.       Getopt::Long::GetOptions($args, @specs);
  1532.     }
  1533.  
  1534.     return $args, @ARGV;
  1535. }
  1536.  
  1537. sub unparse_args {
  1538.   my ($self, $args) = @_;
  1539.   my @out;
  1540.   while (my ($k, $v) = each %$args) {
  1541.     push @out, (UNIVERSAL::isa($v, 'HASH')  ? map {+"--$k", "$_=$v->{$_}"} keys %$v :
  1542.         UNIVERSAL::isa($v, 'ARRAY') ? map {+"--$k", $_} @$v :
  1543.         ("--$k", $v));
  1544.   }
  1545.   return @out;
  1546. }
  1547.  
  1548. sub args {
  1549.     my $self = shift;
  1550.     return wantarray ? %{ $self->{args} } : $self->{args} unless @_;
  1551.     my $key = shift;
  1552.     $self->{args}{$key} = shift if @_;
  1553.     return $self->{args}{$key};
  1554. }
  1555.  
  1556. sub _translate_option {
  1557.   my $self = shift;
  1558.   my $opt  = shift;
  1559.  
  1560.   (my $tr_opt = $opt) =~ tr/-/_/;
  1561.  
  1562.   return $tr_opt if grep $tr_opt =~ /^(?:no_?)?$_$/, qw(
  1563.     create_makefile_pl
  1564.     create_readme
  1565.     extra_compiler_flags
  1566.     extra_linker_flags
  1567.     html_css
  1568.     install_base
  1569.     install_path
  1570.     meta_add
  1571.     meta_merge
  1572.     test_files
  1573.     use_rcfile
  1574.   ); # normalize only selected option names
  1575.  
  1576.   return $opt;
  1577. }
  1578.  
  1579. sub _read_arg {
  1580.   my ($self, $args, $key, $val) = @_;
  1581.  
  1582.   $key = $self->_translate_option($key);
  1583.  
  1584.   if ( exists $args->{$key} ) {
  1585.     $args->{$key} = [ $args->{$key} ] unless ref $args->{$key};
  1586.     push @{$args->{$key}}, $val;
  1587.   } else {
  1588.     $args->{$key} = $val;
  1589.   }
  1590. }
  1591.  
  1592. sub _optional_arg {
  1593.   my $self = shift;
  1594.   my $opt  = shift;
  1595.   my $argv = shift;
  1596.  
  1597.   $opt = $self->_translate_option($opt);
  1598.  
  1599.   my @bool_opts = qw(
  1600.     build_bat
  1601.     create_readme
  1602.     pollute
  1603.     quiet
  1604.     uninst
  1605.     use_rcfile
  1606.     verbose
  1607.   );
  1608.  
  1609.   # inverted boolean options; eg --noverbose or --no-verbose
  1610.   # converted to proper name & returned with false value (verbose, 0)
  1611.   if ( grep $opt =~ /^no[-_]?$_$/, @bool_opts ) {
  1612.     $opt =~ s/^no-?//;
  1613.     return ($opt, 0);
  1614.   }
  1615.  
  1616.   # non-boolean option; return option unchanged along with its argument
  1617.   return ($opt, shift(@$argv)) unless grep $_ eq $opt, @bool_opts;
  1618.  
  1619.   # we're punting a bit here, if an option appears followed by a digit
  1620.   # we take the digit as the argument for the option. If there is
  1621.   # nothing that looks like a digit, we pretent the option is a flag
  1622.   # that is being set and has no argument.
  1623.   my $arg = 1;
  1624.   $arg = shift(@$argv) if @$argv && $argv->[0] =~ /^\d+$/;
  1625.  
  1626.   return ($opt, $arg);
  1627. }
  1628.  
  1629. sub read_args {
  1630.   my $self = shift;
  1631.   my ($action, @argv);
  1632.   (my $args, @_) = $self->cull_options(@_);
  1633.   my %args = %$args;
  1634.  
  1635.   my $opt_re = qr/[\w\-]+/;
  1636.  
  1637.   while (@_) {
  1638.     local $_ = shift;
  1639.     if ( /^(?:--)?($opt_re)=(.*)$/ ) {
  1640.       $self->_read_arg(\%args, $1, $2);
  1641.     } elsif ( /^--($opt_re)$/ ) {
  1642.       my($opt, $arg) = $self->_optional_arg($1, \@_);
  1643.       $self->_read_arg(\%args, $opt, $arg);
  1644.     } elsif ( /^($opt_re)$/ and !defined($action)) {
  1645.       $action = $1;
  1646.     } else {
  1647.       push @argv, $_;
  1648.     }
  1649.   }
  1650.   $args{ARGV} = \@argv;
  1651.  
  1652.   for ('extra_compiler_flags', 'extra_linker_flags') {
  1653.     $args{$_} = [ $self->split_like_shell($args{$_}) ] if exists $args{$_};
  1654.   }
  1655.  
  1656.   # Hashify these parameters
  1657.   for ($self->hash_properties, 'config') {
  1658.     next unless exists $args{$_};
  1659.     my %hash;
  1660.     $args{$_} ||= [];
  1661.     $args{$_} = [ $args{$_} ] unless ref $args{$_};
  1662.     foreach my $arg ( @{$args{$_}} ) {
  1663.       $arg =~ /(\w+)=(.*)/
  1664.     or die "Malformed '$_' argument: '$arg' should be something like 'foo=bar'";
  1665.       $hash{$1} = $2;
  1666.     }
  1667.     $args{$_} = \%hash;
  1668.   }
  1669.  
  1670.   # De-tilde-ify any path parameters
  1671.   for my $key (qw(prefix install_base destdir)) {
  1672.     next if !defined $args{$key};
  1673.     $args{$key} = $self->_detildefy($args{$key});
  1674.   }
  1675.  
  1676.   for my $key (qw(install_path)) {
  1677.     next if !defined $args{$key};
  1678.  
  1679.     for my $subkey (keys %{$args{$key}}) {
  1680.       next if !defined $args{$key}{$subkey};
  1681.       my $subkey_ext = $self->_detildefy($args{$key}{$subkey});
  1682.       if ( $subkey eq 'html' ) { # translate for compatability
  1683.     $args{$key}{binhtml} = $subkey_ext;
  1684.     $args{$key}{libhtml} = $subkey_ext;
  1685.       } else {
  1686.     $args{$key}{$subkey} = $subkey_ext;
  1687.       }
  1688.     }
  1689.   }
  1690.  
  1691.   if ($args{makefile_env_macros}) {
  1692.     require Module::Build::Compat;
  1693.     %args = (%args, Module::Build::Compat->makefile_to_build_macros);
  1694.   }
  1695.   
  1696.   return \%args, $action;
  1697. }
  1698.  
  1699. # Default: do nothing.  Overridden for Unix & Windows.
  1700. sub _detildefy {}
  1701.  
  1702.  
  1703. # merge Module::Build argument lists that have already been parsed
  1704. # by read_args(). Takes two references to option hashes and merges
  1705. # the contents, giving priority to the first.
  1706. sub _merge_arglist {
  1707.   my( $self, $opts1, $opts2 ) = @_;
  1708.  
  1709.   my %new_opts = %$opts1;
  1710.   while (my ($key, $val) = each %$opts2) {
  1711.     if ( exists( $opts1->{$key} ) ) {
  1712.       if ( ref( $val ) eq 'HASH' ) {
  1713.         while (my ($k, $v) = each %$val) {
  1714.       $new_opts{$key}{$k} = $v unless exists( $opts1->{$key}{$k} );
  1715.     }
  1716.       }
  1717.     } else {
  1718.       $new_opts{$key} = $val
  1719.     }
  1720.   }
  1721.  
  1722.   return %new_opts;
  1723. }
  1724.  
  1725. # Look for a home directory on various systems.
  1726. sub _home_dir {
  1727.   my @home_dirs;
  1728.   push( @home_dirs, $ENV{HOME} ) if $ENV{HOME};
  1729.  
  1730.   push( @home_dirs, File::Spec->catpath($ENV{HOMEDRIVE}, $ENV{HOMEPATH}, '') )
  1731.       if $ENV{HOMEDRIVE} && $ENV{HOMEPATH};
  1732.  
  1733.   my @other_home_envs = qw( USERPROFILE APPDATA WINDIR SYS$LOGIN );
  1734.   push( @home_dirs, map $ENV{$_}, grep $ENV{$_}, @other_home_envs );
  1735.  
  1736.   my @real_home_dirs = grep -d, @home_dirs;
  1737.  
  1738.   return wantarray ? @real_home_dirs : shift( @real_home_dirs );
  1739. }
  1740.  
  1741. sub _find_user_config {
  1742.   my $self = shift;
  1743.   my $file = shift;
  1744.   foreach my $dir ( $self->_home_dir ) {
  1745.     my $path = File::Spec->catfile( $dir, $file );
  1746.     return $path if -e $path;
  1747.   }
  1748.   return undef;
  1749. }
  1750.  
  1751. # read ~/.modulebuildrc returning global options '*' and
  1752. # options specific to the currently executing $action.
  1753. sub read_modulebuildrc {
  1754.   my( $self, $action ) = @_;
  1755.  
  1756.   return () unless $self->use_rcfile;
  1757.  
  1758.   my $modulebuildrc;
  1759.   if ( exists($ENV{MODULEBUILDRC}) && $ENV{MODULEBUILDRC} eq 'NONE' ) {
  1760.     return ();
  1761.   } elsif ( exists($ENV{MODULEBUILDRC}) && -e $ENV{MODULEBUILDRC} ) {
  1762.     $modulebuildrc = $ENV{MODULEBUILDRC};
  1763.   } elsif ( exists($ENV{MODULEBUILDRC}) ) {
  1764.     $self->log_warn("WARNING: Can't find resource file " .
  1765.             "'$ENV{MODULEBUILDRC}' defined in environment.\n" .
  1766.             "No options loaded\n");
  1767.     return ();
  1768.   } else {
  1769.     $modulebuildrc = $self->_find_user_config( '.modulebuildrc' );
  1770.     return () unless $modulebuildrc;
  1771.   }
  1772.  
  1773.   my $fh = IO::File->new( $modulebuildrc )
  1774.       or die "Can't open $modulebuildrc: $!";
  1775.  
  1776.   my %options; my $buffer = '';
  1777.   while (defined( my $line = <$fh> )) {
  1778.     chomp( $line );
  1779.     $line =~ s/#.*$//;
  1780.     next unless length( $line );
  1781.  
  1782.     if ( $line =~ /^\S/ ) {
  1783.       if ( $buffer ) {
  1784.     my( $action, $options ) = split( /\s+/, $buffer, 2 );
  1785.     $options{$action} .= $options . ' ';
  1786.     $buffer = '';
  1787.       }
  1788.       $buffer = $line;
  1789.     } else {
  1790.       $buffer .= $line;
  1791.     }
  1792.   }
  1793.  
  1794.   if ( $buffer ) { # anything left in $buffer ?
  1795.     my( $action, $options ) = split( /\s+/, $buffer, 2 );
  1796.     $options{$action} .= $options . ' '; # merge if more than one line
  1797.   }
  1798.  
  1799.   my ($global_opts) =
  1800.     $self->read_args( $self->split_like_shell( $options{'*'} || '' ) );
  1801.   my ($action_opts) =
  1802.     $self->read_args( $self->split_like_shell( $options{$action} || '' ) );
  1803.  
  1804.   # specific $action options take priority over global options '*'
  1805.   return $self->_merge_arglist( $action_opts, $global_opts );
  1806. }
  1807.  
  1808. # merge the relevant options in ~/.modulebuildrc into Module::Build's
  1809. # option list where they do not conflict with commandline options.
  1810. sub merge_modulebuildrc {
  1811.   my( $self, $action, %cmdline_opts ) = @_;
  1812.   my %rc_opts = $self->read_modulebuildrc( $action || $self->{action} || 'build' );
  1813.   my %new_opts = $self->_merge_arglist( \%cmdline_opts, \%rc_opts );
  1814.   $self->merge_args( $action, %new_opts );
  1815. }
  1816.  
  1817. sub merge_args {
  1818.   my ($self, $action, %args) = @_;
  1819.   $self->{action} = $action if defined $action;
  1820.  
  1821.   my %additive = map { $_ => 1 } $self->hash_properties;
  1822.  
  1823.   # Extract our 'properties' from $cmd_args, the rest are put in 'args'.
  1824.   while (my ($key, $val) = each %args) {
  1825.     $self->{phash}{runtime_params}->access( $key => $val )
  1826.       if $self->valid_property($key);
  1827.  
  1828.     if ($key eq 'config') {
  1829.       $self->config($_ => $val->{$_}) foreach keys %$val;
  1830.     } else {
  1831.       my $add_to = ( $additive{$key} ? $self->{properties}{$key}
  1832.              : $self->valid_property($key) ? $self->{properties}
  1833.              : $self->{args});
  1834.  
  1835.       if ($additive{$key}) {
  1836.     $add_to->{$_} = $val->{$_} foreach keys %$val;
  1837.       } else {
  1838.     $add_to->{$key} = $val;
  1839.       }
  1840.     }
  1841.   }
  1842. }
  1843.  
  1844. sub cull_args {
  1845.   my $self = shift;
  1846.   my ($args, $action) = $self->read_args(@_);
  1847.   $self->merge_args($action, %$args);
  1848.   $self->merge_modulebuildrc( $action, %$args );
  1849. }
  1850.  
  1851. sub super_classes {
  1852.   my ($self, $class, $seen) = @_;
  1853.   $class ||= ref($self) || $self;
  1854.   $seen  ||= {};
  1855.   
  1856.   no strict 'refs';
  1857.   my @super = grep {not $seen->{$_}++} $class, @{ $class . '::ISA' };
  1858.   return @super, map {$self->super_classes($_,$seen)} @super;
  1859. }
  1860.  
  1861. sub known_actions {
  1862.   my ($self) = @_;
  1863.  
  1864.   my %actions;
  1865.   no strict 'refs';
  1866.   
  1867.   foreach my $class ($self->super_classes) {
  1868.     foreach ( keys %{ $class . '::' } ) {
  1869.       $actions{$1}++ if /^ACTION_(\w+)/;
  1870.     }
  1871.   }
  1872.  
  1873.   return wantarray ? sort keys %actions : \%actions;
  1874. }
  1875.  
  1876. sub get_action_docs {
  1877.   my ($self, $action) = @_;
  1878.   my $actions = $self->known_actions;
  1879.   die "No known action '$action'" unless $actions->{$action};
  1880.  
  1881.   my ($files_found, @docs) = (0);
  1882.   foreach my $class ($self->super_classes) {
  1883.     (my $file = $class) =~ s{::}{/}g;
  1884.     # NOTE: silently skipping relative paths if any chdir() happened
  1885.     $file = $INC{$file . '.pm'} or next;
  1886.     my $fh = IO::File->new("< $file") or next;
  1887.     $files_found++;
  1888.  
  1889.     # Code below modified from /usr/bin/perldoc
  1890.  
  1891.     # Skip to ACTIONS section
  1892.     local $_;
  1893.     while (<$fh>) {
  1894.       last if /^=head1 ACTIONS\s/;
  1895.     }
  1896.  
  1897.     # Look for our action and determine the style
  1898.     my $style;
  1899.     while (<$fh>) {
  1900.       last if /^=head1 /;
  1901.  
  1902.       # only item and head2 are allowed (3&4 are not in 5.005)
  1903.       if(/^=(item|head2)\s+\Q$action\E\b/) {
  1904.         $style = $1;
  1905.         push @docs, $_;
  1906.         last;
  1907.       }
  1908.     }
  1909.     $style or next; # not here
  1910.  
  1911.     # and the content
  1912.     if($style eq 'item') {
  1913.       my ($found, $inlist) = (0, 0);
  1914.       while (<$fh>) {
  1915.         if (/^=(item|back)/) {
  1916.           last unless $inlist;
  1917.         }
  1918.         push @docs, $_;
  1919.         ++$inlist if /^=over/;
  1920.         --$inlist if /^=back/;
  1921.       }
  1922.     }
  1923.     else { # head2 style
  1924.       # stop at anything equal or greater than the found level
  1925.       while (<$fh>) {
  1926.         last if(/^=(?:head[12]|cut)/);
  1927.         push @docs, $_;
  1928.       }
  1929.     }
  1930.     # TODO maybe disallow overriding just pod for an action
  1931.     # TODO and possibly: @docs and last;
  1932.   }
  1933.  
  1934.   unless ($files_found) {
  1935.     $@ = "Couldn't find any documentation to search";
  1936.     return;
  1937.   }
  1938.   unless (@docs) {
  1939.     $@ = "Couldn't find any docs for action '$action'";
  1940.     return;
  1941.   }
  1942.   
  1943.   return join '', @docs;
  1944. }
  1945.  
  1946. sub ACTION_prereq_report {
  1947.   my $self = shift;
  1948.   $self->log_info( $self->prereq_report );
  1949. }
  1950.  
  1951. sub prereq_report {
  1952.   my $self = shift;
  1953.   my @types = @{ $self->prereq_action_types };
  1954.   my $info = { map { $_ => $self->$_() } @types };
  1955.  
  1956.   my $output = '';
  1957.   foreach my $type (@types) {
  1958.     my $prereqs = $info->{$type};
  1959.     next unless %$prereqs;
  1960.     $output .= "\n$type:\n";
  1961.     my $mod_len = 2;
  1962.     my $ver_len = 4;
  1963.     my %mods;
  1964.     while ( my ($modname, $spec) = each %$prereqs ) {
  1965.       my $len  = length $modname;
  1966.       $mod_len = $len if $len > $mod_len;
  1967.       $spec    ||= '0';
  1968.       $len     = length $spec;
  1969.       $ver_len = $len if $len > $ver_len;
  1970.  
  1971.       my $mod = $self->check_installed_status($modname, $spec);
  1972.       $mod->{name} = $modname;
  1973.       $mod->{ok} ||= 0;
  1974.       $mod->{ok} = ! $mod->{ok} if $type =~ /^(\w+_)?conflicts$/;
  1975.  
  1976.       $mods{lc $modname} = $mod;
  1977.     }
  1978.  
  1979.     my $space  = q{ } x ($mod_len - 3);
  1980.     my $vspace = q{ } x ($ver_len - 3);
  1981.     my $sline  = q{-} x ($mod_len - 3);
  1982.     my $vline  = q{-} x ($ver_len - 3);
  1983.     my $disposition = ($type =~ /^(\w+_)?conflicts$/) ?
  1984.                         'Clash' : 'Need';
  1985.     $output .=
  1986.       "    Module $space  $disposition $vspace  Have\n".
  1987.       "    ------$sline+------$vline-+----------\n";
  1988.  
  1989.  
  1990.     for my $k (sort keys %mods) {
  1991.       my $mod = $mods{$k};
  1992.       my $space  = q{ } x ($mod_len - length $k);
  1993.       my $vspace = q{ } x ($ver_len - length $mod->{need});
  1994.       my $f = $mod->{ok} ? ' ' : '!';
  1995.       $output .=
  1996.         "  $f $mod->{name} $space     $mod->{need}  $vspace   ".
  1997.         (defined($mod->{have}) ? $mod->{have} : "")."\n";
  1998.     }
  1999.   }
  2000.   return $output;
  2001. }
  2002.  
  2003. sub ACTION_help {
  2004.   my ($self) = @_;
  2005.   my $actions = $self->known_actions;
  2006.   
  2007.   if (@{$self->{args}{ARGV}}) {
  2008.     my $msg = eval {$self->get_action_docs($self->{args}{ARGV}[0], $actions)};
  2009.     print $@ ? "$@\n" : $msg;
  2010.     return;
  2011.   }
  2012.  
  2013.   print <<EOF;
  2014.  
  2015.  Usage: $0 <action> arg1=value arg2=value ...
  2016.  Example: $0 test verbose=1
  2017.  
  2018.  Actions defined:
  2019. EOF
  2020.   
  2021.   print $self->_action_listing($actions);
  2022.  
  2023.   print "\nRun `Build help <action>` for details on an individual action.\n";
  2024.   print "See `perldoc Module::Build` for complete documentation.\n";
  2025. }
  2026.  
  2027. sub _action_listing {
  2028.   my ($self, $actions) = @_;
  2029.  
  2030.   # Flow down columns, not across rows
  2031.   my @actions = sort keys %$actions;
  2032.   @actions = map $actions[($_ + ($_ % 2) * @actions) / 2],  0..$#actions;
  2033.   
  2034.   my $out = '';
  2035.   while (my ($one, $two) = splice @actions, 0, 2) {
  2036.     $out .= sprintf("  %-12s                   %-12s\n", $one, $two||'');
  2037.   }
  2038.   return $out;
  2039. }
  2040.  
  2041. sub ACTION_retest {
  2042.   my ($self) = @_;
  2043.   
  2044.   # Protect others against our @INC changes
  2045.   local @INC = @INC;
  2046.  
  2047.   # Filter out nonsensical @INC entries - some versions of
  2048.   # Test::Harness will really explode the number of entries here
  2049.   @INC = grep {ref() || -d} @INC if @INC > 100;
  2050.  
  2051.   $self->do_tests;
  2052. }
  2053.  
  2054. sub ACTION_testall {
  2055.   my ($self) = @_;
  2056.  
  2057.   my @types;
  2058.   for my $action (grep { $_ ne 'all' } $self->get_test_types) {
  2059.     # XXX We can't just dispatch because we get multiple summaries but
  2060.     # we'll need to dispatch to support custom setup/teardown in the
  2061.     # action.  To support that, we'll need to call something besides
  2062.     # Harness::runtests() because we'll need to collect the results in
  2063.     # parts, then run the summary.
  2064.     push(@types, $action);
  2065.     #$self->_call_action( "test$action" );
  2066.   }
  2067.   $self->generic_test(types => ['default', @types]);
  2068. }
  2069.  
  2070. sub get_test_types {
  2071.   my ($self) = @_;
  2072.  
  2073.   my $t = $self->{properties}->{test_types};
  2074.   return ( defined $t ? ( keys %$t ) : () );
  2075. }
  2076.  
  2077.  
  2078. sub ACTION_test {
  2079.   my ($self) = @_;
  2080.   $self->generic_test(type => 'default');
  2081. }
  2082.  
  2083. sub generic_test {
  2084.   my $self = shift;
  2085.   (@_ % 2) and croak('Odd number of elements in argument hash');
  2086.   my %args = @_;
  2087.  
  2088.   my $p = $self->{properties};
  2089.  
  2090.   my @types = (
  2091.     (exists($args{type})  ? $args{type} : ()), 
  2092.     (exists($args{types}) ? @{$args{types}} : ()),
  2093.   );
  2094.   @types or croak "need some types of tests to check";
  2095.  
  2096.   my %test_types = (
  2097.     default => '.t',
  2098.     (defined($p->{test_types}) ? %{$p->{test_types}} : ()),
  2099.   );
  2100.  
  2101.   for my $type (@types) {
  2102.     croak "$type not defined in test_types!"
  2103.       unless defined $test_types{ $type };
  2104.   }
  2105.  
  2106.   # we use local here because it ends up two method calls deep
  2107.   local $p->{test_file_exts} = [ @test_types{@types} ];
  2108.   $self->depends_on('code');
  2109.  
  2110.   # Protect others against our @INC changes
  2111.   local @INC = @INC;
  2112.  
  2113.   # Make sure we test the module in blib/
  2114.   unshift @INC, (File::Spec->catdir($p->{base_dir}, $self->blib, 'lib'),
  2115.          File::Spec->catdir($p->{base_dir}, $self->blib, 'arch'));
  2116.  
  2117.   # Filter out nonsensical @INC entries - some versions of
  2118.   # Test::Harness will really explode the number of entries here
  2119.   @INC = grep {ref() || -d} @INC if @INC > 100;
  2120.  
  2121.   $self->do_tests;
  2122. }
  2123.  
  2124. sub do_tests {
  2125.   my $self = shift;
  2126.   my $p = $self->{properties};
  2127.   require Test::Harness;
  2128.  
  2129.   # Do everything in our power to work with all versions of Test::Harness
  2130.   my @harness_switches = $p->{debugger} ? qw(-w -d) : ();
  2131.   local $Test::Harness::switches    = join ' ', grep defined, $Test::Harness::switches, @harness_switches;
  2132.   local $Test::Harness::Switches    = join ' ', grep defined, $Test::Harness::Switches, @harness_switches;
  2133.   local $ENV{HARNESS_PERL_SWITCHES} = join ' ', grep defined, $ENV{HARNESS_PERL_SWITCHES}, @harness_switches;
  2134.   
  2135.   $Test::Harness::switches = undef   unless length $Test::Harness::switches;
  2136.   $Test::Harness::Switches = undef   unless length $Test::Harness::Switches;
  2137.   delete $ENV{HARNESS_PERL_SWITCHES} unless length $ENV{HARNESS_PERL_SWITCHES};
  2138.   
  2139.   local ($Test::Harness::verbose,
  2140.      $Test::Harness::Verbose,
  2141.      $ENV{TEST_VERBOSE},
  2142.          $ENV{HARNESS_VERBOSE}) = ($p->{verbose} || 0) x 4;
  2143.  
  2144.   my $tests = $self->find_test_files;
  2145.  
  2146.   if (@$tests) {
  2147.     # Work around a Test::Harness bug that loses the particular perl
  2148.     # we're running under.  $self->perl is trustworthy, but $^X isn't.
  2149.     local $^X = $self->perl;
  2150.     Test::Harness::runtests(@$tests);
  2151.   } else {
  2152.     $self->log_info("No tests defined.\n");
  2153.   }
  2154.  
  2155.   # This will get run and the user will see the output.  It doesn't
  2156.   # emit Test::Harness-style output.
  2157.   if (-e 'visual.pl') {
  2158.     $self->run_perl_script('visual.pl', '-Mblib='.$self->blib);
  2159.   }
  2160. }
  2161.  
  2162. sub test_files {
  2163.   my $self = shift;
  2164.   my $p = $self->{properties};
  2165.   if (@_) {
  2166.     return $p->{test_files} = (@_ == 1 ? shift : [@_]);
  2167.   }
  2168.   return $self->find_test_files;
  2169. }
  2170.  
  2171. sub expand_test_dir {
  2172.   my ($self, $dir) = @_;
  2173.   my $exts = $self->{properties}{test_file_exts} || ['.t'];
  2174.  
  2175.   return sort map { @{$self->rscan_dir($dir, qr{^[^.].*\Q$_\E$})} } @$exts
  2176.     if $self->recursive_test_files;
  2177.  
  2178.   return sort map { glob File::Spec->catfile($dir, "*$_") } @$exts;
  2179. }
  2180.  
  2181. sub ACTION_testdb {
  2182.   my ($self) = @_;
  2183.   local $self->{properties}{debugger} = 1;
  2184.   $self->depends_on('test');
  2185. }
  2186.  
  2187. sub ACTION_testcover {
  2188.   my ($self) = @_;
  2189.  
  2190.   unless (Module::Build::ModuleInfo->find_module_by_name('Devel::Cover')) {
  2191.     warn("Cannot run testcover action unless Devel::Cover is installed.\n");
  2192.     return;
  2193.   }
  2194.  
  2195.   $self->add_to_cleanup('coverage', 'cover_db');
  2196.   $self->depends_on('code');
  2197.  
  2198.   # See whether any of the *.pm files have changed since last time
  2199.   # testcover was run.  If so, start over.
  2200.   if (-e 'cover_db') {
  2201.     my $pm_files = $self->rscan_dir
  2202.         (File::Spec->catdir($self->blib, 'lib'), file_qr('\.pm$') );
  2203.     my $cover_files = $self->rscan_dir('cover_db', sub {-f $_ and not /\.html$/});
  2204.     
  2205.     $self->do_system(qw(cover -delete))
  2206.       unless $self->up_to_date($pm_files,         $cover_files)
  2207.       && $self->up_to_date($self->test_files, $cover_files);
  2208.   }
  2209.  
  2210.   local $Test::Harness::switches    = 
  2211.   local $Test::Harness::Switches    = 
  2212.   local $ENV{HARNESS_PERL_SWITCHES} = "-MDevel::Cover";
  2213.  
  2214.   $self->depends_on('test');
  2215.   $self->do_system('cover');
  2216. }
  2217.  
  2218. sub ACTION_code {
  2219.   my ($self) = @_;
  2220.   
  2221.   # All installable stuff gets created in blib/ .
  2222.   # Create blib/arch to keep blib.pm happy
  2223.   my $blib = $self->blib;
  2224.   $self->add_to_cleanup($blib);
  2225.   File::Path::mkpath( File::Spec->catdir($blib, 'arch') );
  2226.   
  2227.   if (my $split = $self->autosplit) {
  2228.     $self->autosplit_file($_, $blib) for ref($split) ? @$split : ($split);
  2229.   }
  2230.   
  2231.   foreach my $element (@{$self->build_elements}) {
  2232.     my $method = "process_${element}_files";
  2233.     $method = "process_files_by_extension" unless $self->can($method);
  2234.     $self->$method($element);
  2235.   }
  2236.  
  2237.   $self->depends_on('config_data');
  2238. }
  2239.  
  2240. sub ACTION_build {
  2241.   my $self = shift;
  2242.   $self->depends_on('code');
  2243.   $self->depends_on('docs');
  2244. }
  2245.  
  2246. sub process_files_by_extension {
  2247.   my ($self, $ext) = @_;
  2248.   
  2249.   my $method = "find_${ext}_files";
  2250.   my $files = $self->can($method) ? $self->$method() : $self->_find_file_by_type($ext,  'lib');
  2251.   
  2252.   while (my ($file, $dest) = each %$files) {
  2253.     $self->copy_if_modified(from => $file, to => File::Spec->catfile($self->blib, $dest) );
  2254.   }
  2255. }
  2256.  
  2257. sub process_support_files {
  2258.   my $self = shift;
  2259.   my $p = $self->{properties};
  2260.   return unless $p->{c_source};
  2261.   
  2262.   push @{$p->{include_dirs}}, $p->{c_source};
  2263.   
  2264.   my $files = $self->rscan_dir($p->{c_source}, file_qr('\.c(pp)?$'));
  2265.   foreach my $file (@$files) {
  2266.     push @{$p->{objects}}, $self->compile_c($file);
  2267.   }
  2268. }
  2269.  
  2270. sub process_PL_files {
  2271.   my ($self) = @_;
  2272.   my $files = $self->find_PL_files;
  2273.   
  2274.   while (my ($file, $to) = each %$files) {
  2275.     unless ($self->up_to_date( $file, $to )) {
  2276.       $self->run_perl_script($file, [], [@$to]) or die "$file failed";
  2277.       $self->add_to_cleanup(@$to);
  2278.     }
  2279.   }
  2280. }
  2281.  
  2282. sub process_xs_files {
  2283.   my $self = shift;
  2284.   my $files = $self->find_xs_files;
  2285.   while (my ($from, $to) = each %$files) {
  2286.     unless ($from eq $to) {
  2287.       $self->add_to_cleanup($to);
  2288.       $self->copy_if_modified( from => $from, to => $to );
  2289.     }
  2290.     $self->process_xs($to);
  2291.   }
  2292. }
  2293.  
  2294. sub process_pod_files { shift()->process_files_by_extension(shift()) }
  2295. sub process_pm_files  { shift()->process_files_by_extension(shift()) }
  2296.  
  2297. sub process_script_files {
  2298.   my $self = shift;
  2299.   my $files = $self->find_script_files;
  2300.   return unless keys %$files;
  2301.  
  2302.   my $script_dir = File::Spec->catdir($self->blib, 'script');
  2303.   File::Path::mkpath( $script_dir );
  2304.   
  2305.   foreach my $file (keys %$files) {
  2306.     my $result = $self->copy_if_modified($file, $script_dir, 'flatten') or next;
  2307.     $self->fix_shebang_line($result) unless $self->is_vmsish;
  2308.     $self->make_executable($result);
  2309.   }
  2310. }
  2311.  
  2312. sub find_PL_files {
  2313.   my $self = shift;
  2314.   if (my $files = $self->{properties}{PL_files}) {
  2315.     # 'PL_files' is given as a Unix file spec, so we localize_file_path().
  2316.     
  2317.     if (UNIVERSAL::isa($files, 'ARRAY')) {
  2318.       return { map {$_, [/^(.*)\.PL$/]}
  2319.            map $self->localize_file_path($_),
  2320.            @$files };
  2321.  
  2322.     } elsif (UNIVERSAL::isa($files, 'HASH')) {
  2323.       my %out;
  2324.       while (my ($file, $to) = each %$files) {
  2325.     $out{ $self->localize_file_path($file) } = [ map $self->localize_file_path($_),
  2326.                              ref $to ? @$to : ($to) ];
  2327.       }
  2328.       return \%out;
  2329.  
  2330.     } else {
  2331.       die "'PL_files' must be a hash reference or array reference";
  2332.     }
  2333.   }
  2334.   
  2335.   return unless -d 'lib';
  2336.   return { map {$_, [/^(.*)\.PL$/i ]} @{ $self->rscan_dir('lib',
  2337.                                                           file_qr('\.PL$')) } };
  2338. }
  2339.  
  2340. sub find_pm_files  { shift->_find_file_by_type('pm',  'lib') }
  2341. sub find_pod_files { shift->_find_file_by_type('pod', 'lib') }
  2342. sub find_xs_files  { shift->_find_file_by_type('xs',  'lib') }
  2343.  
  2344. sub find_script_files {
  2345.   my $self = shift;
  2346.   if (my $files = $self->script_files) {
  2347.     # Always given as a Unix file spec.  Values in the hash are
  2348.     # meaningless, but we preserve if present.
  2349.     return { map {$self->localize_file_path($_), $files->{$_}} keys %$files };
  2350.   }
  2351.   
  2352.   # No default location for script files
  2353.   return {};
  2354. }
  2355.  
  2356. sub find_test_files {
  2357.   my $self = shift;
  2358.   my $p = $self->{properties};
  2359.  
  2360.   if (my $files = $p->{test_files}) {
  2361.     $files = [keys %$files] if UNIVERSAL::isa($files, 'HASH');
  2362.     $files = [map { -d $_ ? $self->expand_test_dir($_) : $_ }
  2363.           map glob,
  2364.           $self->split_like_shell($files)];
  2365.     
  2366.     # Always given as a Unix file spec.
  2367.     return [ map $self->localize_file_path($_), @$files ];
  2368.     
  2369.   } else {
  2370.     # Find all possible tests in t/ or test.pl
  2371.     my @tests;
  2372.     push @tests, 'test.pl'                          if -e 'test.pl';
  2373.     push @tests, $self->expand_test_dir('t')        if -e 't' and -d _;
  2374.     return \@tests;
  2375.   }
  2376. }
  2377.  
  2378. sub _find_file_by_type {
  2379.   my ($self, $type, $dir) = @_;
  2380.   
  2381.   if (my $files = $self->{properties}{"${type}_files"}) {
  2382.     # Always given as a Unix file spec
  2383.     return { map $self->localize_file_path($_), %$files };
  2384.   }
  2385.   
  2386.   return {} unless -d $dir;
  2387.   return { map {$_, $_}
  2388.        map $self->localize_file_path($_),
  2389.        grep !/\.\#/,
  2390.        @{ $self->rscan_dir($dir, file_qr("\\.$type\$")) } };
  2391. }
  2392.  
  2393. sub localize_file_path {
  2394.   my ($self, $path) = @_;
  2395.   $path =~ s/\.\z// if $self->is_vmsish;
  2396.   return File::Spec->catfile( split m{/}, $path );
  2397. }
  2398.  
  2399. sub localize_dir_path {
  2400.   my ($self, $path) = @_;
  2401.   return File::Spec->catdir( split m{/}, $path );
  2402. }
  2403.  
  2404. sub fix_shebang_line { # Adapted from fixin() in ExtUtils::MM_Unix 1.35
  2405.   my ($self, @files) = @_;
  2406.   my $c = ref($self) ? $self->{config} : 'Module::Build::Config';
  2407.   
  2408.   my ($does_shbang) = $c->get('sharpbang') =~ /^\s*\#\!/;
  2409.   for my $file (@files) {
  2410.     my $FIXIN = IO::File->new($file) or die "Can't process '$file': $!";
  2411.     local $/ = "\n";
  2412.     chomp(my $line = <$FIXIN>);
  2413.     next unless $line =~ s/^\s*\#!\s*//;     # Not a shbang file.
  2414.     
  2415.     my ($cmd, $arg) = (split(' ', $line, 2), '');
  2416.     next unless $cmd =~ /perl/i;
  2417.     my $interpreter = $self->{properties}{perl};
  2418.     
  2419.     $self->log_verbose("Changing sharpbang in $file to $interpreter");
  2420.     my $shb = '';
  2421.     $shb .= $c->get('sharpbang')."$interpreter $arg\n" if $does_shbang;
  2422.     
  2423.     # I'm not smart enough to know the ramifications of changing the
  2424.     # embedded newlines here to \n, so I leave 'em in.
  2425.     $shb .= qq{
  2426. eval 'exec $interpreter $arg -S \$0 \${1+"\$\@"}'
  2427.     if 0; # not running under some shell
  2428. } unless $self->is_windowsish; # this won't work on win32, so don't
  2429.     
  2430.     my $FIXOUT = IO::File->new(">$file.new")
  2431.       or die "Can't create new $file: $!\n";
  2432.     
  2433.     # Print out the new #! line (or equivalent).
  2434.     local $\;
  2435.     undef $/; # Was localized above
  2436.     print $FIXOUT $shb, <$FIXIN>;
  2437.     close $FIXIN;
  2438.     close $FIXOUT;
  2439.     
  2440.     rename($file, "$file.bak")
  2441.       or die "Can't rename $file to $file.bak: $!";
  2442.     
  2443.     rename("$file.new", $file)
  2444.       or die "Can't rename $file.new to $file: $!";
  2445.     
  2446.     $self->delete_filetree("$file.bak")
  2447.       or $self->log_warn("Couldn't clean up $file.bak, leaving it there");
  2448.     
  2449.     $self->do_system($c->get('eunicefix'), $file) if $c->get('eunicefix') ne ':';
  2450.   }
  2451. }
  2452.  
  2453.  
  2454. sub ACTION_testpod {
  2455.   my $self = shift;
  2456.   $self->depends_on('docs');
  2457.   
  2458.   eval q{use Test::Pod 0.95; 1}
  2459.     or die "The 'testpod' action requires Test::Pod version 0.95";
  2460.  
  2461.   my @files = sort keys %{$self->_find_pods($self->libdoc_dirs)},
  2462.                    keys %{$self->_find_pods
  2463.                              ($self->bindoc_dirs,
  2464.                               exclude => [ file_qr('\.bat$') ])}
  2465.     or die "Couldn't find any POD files to test\n";
  2466.  
  2467.   { package Module::Build::PodTester;  # Don't want to pollute the main namespace
  2468.     Test::Pod->import( tests => scalar @files );
  2469.     pod_file_ok($_) foreach @files;
  2470.   }
  2471. }
  2472.  
  2473. sub ACTION_testpodcoverage {
  2474.   my $self = shift;
  2475.  
  2476.   $self->depends_on('docs');
  2477.   
  2478.   eval q{use Test::Pod::Coverage 1.00; 1}
  2479.     or die "The 'testpodcoverage' action requires ",
  2480.            "Test::Pod::Coverage version 1.00";
  2481.  
  2482.   # TODO this needs test coverage!
  2483.  
  2484.   # XXX work-around a bug in Test::Pod::Coverage previous to v1.09
  2485.   # Make sure we test the module in blib/
  2486.   local @INC = @INC;
  2487.   my $p = $self->{properties};
  2488.   unshift(@INC,
  2489.     # XXX any reason to include arch?
  2490.     File::Spec->catdir($p->{base_dir}, $self->blib, 'lib'),
  2491.     #File::Spec->catdir($p->{base_dir}, $self->blib, 'arch')
  2492.   );
  2493.  
  2494.   all_pod_coverage_ok();
  2495. }
  2496.  
  2497. sub ACTION_docs {
  2498.   my $self = shift;
  2499.  
  2500.   $self->depends_on('code');
  2501.   $self->depends_on('manpages', 'html');
  2502. }
  2503.  
  2504. # Given a file type, will return true if the file type would normally
  2505. # be installed when neither install-base nor prefix has been set.
  2506. # I.e. it will be true only if the path is set from Config.pm or
  2507. # set explicitly by the user via install-path.
  2508. sub _is_default_installable {
  2509.   my $self = shift;
  2510.   my $type = shift;
  2511.   return ( $self->install_destination($type) &&
  2512.            ( $self->install_path($type) ||
  2513.          $self->install_sets($self->installdirs)->{$type} )
  2514.      ) ? 1 : 0;
  2515. }
  2516.  
  2517. sub ACTION_manpages {
  2518.   my $self = shift;
  2519.  
  2520.   return unless $self->_mb_feature('manpage_support');
  2521.  
  2522.   $self->depends_on('code');
  2523.  
  2524.   foreach my $type ( qw(bin lib) ) {
  2525.     my $files = $self->_find_pods( $self->{properties}{"${type}doc_dirs"},
  2526.                                    exclude => [ file_qr('\.bat$') ] );
  2527.     next unless %$files;
  2528.  
  2529.     my $sub = $self->can("manify_${type}_pods");
  2530.     next unless defined( $sub );
  2531.  
  2532.     if ( $self->invoked_action eq 'manpages' ) {
  2533.       $self->$sub();
  2534.     } elsif ( $self->_is_default_installable("${type}doc") ) {
  2535.       $self->$sub();
  2536.     }
  2537.   }
  2538.  
  2539. }
  2540.  
  2541. sub manify_bin_pods {
  2542.   my $self    = shift;
  2543.  
  2544.   my $files   = $self->_find_pods( $self->{properties}{bindoc_dirs},
  2545.                                    exclude => [ file_qr('\.bat$') ] );
  2546.   return unless keys %$files;
  2547.  
  2548.   my $mandir = File::Spec->catdir( $self->blib, 'bindoc' );
  2549.   File::Path::mkpath( $mandir, 0, oct(777) );
  2550.  
  2551.   require Pod::Man;
  2552.   foreach my $file (keys %$files) {
  2553.     # Pod::Simple based parsers only support one document per instance.
  2554.     # This is expected to change in a future version (Pod::Simple > 3.03).
  2555.     my $parser  = Pod::Man->new( section => '1p' ); # binaries go in section 1p
  2556.     my $manpage = $self->man1page_name( $file ) . '.' .
  2557.               $self->config( 'man1ext' );
  2558.     my $outfile = File::Spec->catfile($mandir, $manpage);
  2559.     next if $self->up_to_date( $file, $outfile );
  2560.     $self->log_info("Manifying $file -> $outfile\n");
  2561.     $parser->parse_from_file( $file, $outfile );
  2562.     $files->{$file} = $outfile;
  2563.   }
  2564. }
  2565.  
  2566. sub manify_lib_pods {
  2567.   my $self    = shift;
  2568.  
  2569.   my $files   = $self->_find_pods($self->{properties}{libdoc_dirs});
  2570.   return unless keys %$files;
  2571.  
  2572.   my $mandir = File::Spec->catdir( $self->blib, 'libdoc' );
  2573.   File::Path::mkpath( $mandir, 0, oct(777) );
  2574.  
  2575.   require Pod::Man;
  2576.   while (my ($file, $relfile) = each %$files) {
  2577.     # Pod::Simple based parsers only support one document per instance.
  2578.     # This is expected to change in a future version (Pod::Simple > 3.03).
  2579.     my $parser  = Pod::Man->new( section => '3pm' ); # libraries go in section 3pm
  2580.     my $manpage = $self->man3page_name( $relfile ) . '.' .
  2581.               $self->config( 'man3ext' );
  2582.     my $outfile = File::Spec->catfile( $mandir, $manpage);
  2583.     next if $self->up_to_date( $file, $outfile );
  2584.     $self->log_info("Manifying $file -> $outfile\n");
  2585.     $parser->parse_from_file( $file, $outfile );
  2586.     $files->{$file} = $outfile;
  2587.   }
  2588. }
  2589.  
  2590. sub _find_pods {
  2591.   my ($self, $dirs, %args) = @_;
  2592.   my %files;
  2593.   foreach my $spec (@$dirs) {
  2594.     my $dir = $self->localize_dir_path($spec);
  2595.     next unless -e $dir;
  2596.  
  2597.     FILE: foreach my $file ( @{ $self->rscan_dir( $dir ) } ) {
  2598.       foreach my $regexp ( @{ $args{exclude} } ) {
  2599.     next FILE if $file =~ $regexp;
  2600.       }
  2601.       $files{$file} = File::Spec->abs2rel($file, $dir) if $self->contains_pod( $file )
  2602.     }
  2603.   }
  2604.   return \%files;
  2605. }
  2606.  
  2607. sub contains_pod {
  2608.   my ($self, $file) = @_;
  2609.   return '' unless -T $file;  # Only look at text files
  2610.   
  2611.   my $fh = IO::File->new( $file ) or die "Can't open $file: $!";
  2612.   while (my $line = <$fh>) {
  2613.     return 1 if $line =~ /^\=(?:head|pod|item)/;
  2614.   }
  2615.   
  2616.   return '';
  2617. }
  2618.  
  2619. sub ACTION_html {
  2620.   my $self = shift;
  2621.  
  2622.   return unless $self->_mb_feature('HTML_support');
  2623.  
  2624.   $self->depends_on('code');
  2625.  
  2626.   foreach my $type ( qw(bin lib) ) {
  2627.     my $files = $self->_find_pods( $self->{properties}{"${type}doc_dirs"},
  2628.                    exclude => 
  2629.                                         [ file_qr('\.(?:bat|com|html)$') ] );
  2630.     next unless %$files;
  2631.  
  2632.     if ( $self->invoked_action eq 'html' ) {
  2633.       $self->htmlify_pods( $type );
  2634.     } elsif ( $self->_is_default_installable("${type}html") ) {
  2635.       $self->htmlify_pods( $type );
  2636.     }
  2637.   }
  2638.  
  2639. }
  2640.  
  2641.  
  2642. # 1) If it's an ActiveState perl install, we need to run
  2643. #    ActivePerl::DocTools->UpdateTOC;
  2644. # 2) Links to other modules are not being generated
  2645. sub htmlify_pods {
  2646.   my $self = shift;
  2647.   my $type = shift;
  2648.   my $htmldir = shift || File::Spec->catdir($self->blib, "${type}html");
  2649.  
  2650.   require Module::Build::PodParser;
  2651.   require Pod::Html;
  2652.  
  2653.   $self->add_to_cleanup('pod2htm*');
  2654.  
  2655.   my $pods = $self->_find_pods( $self->{properties}{"${type}doc_dirs"},
  2656.                                 exclude => [ file_qr('\.(?:bat|com|html)$') ] );
  2657.   return unless %$pods;  # nothing to do
  2658.  
  2659.   unless ( -d $htmldir ) {
  2660.     File::Path::mkpath($htmldir, 0, oct(755))
  2661.       or die "Couldn't mkdir $htmldir: $!";
  2662.   }
  2663.  
  2664.   my @rootdirs = ($type eq 'bin') ? qw(bin) :
  2665.       $self->installdirs eq 'core' ? qw(lib) : qw(site lib);
  2666.  
  2667.   my $podpath = join ':',
  2668.                 map  $_->[1],
  2669.                 grep -e $_->[0],
  2670.                 map  [File::Spec->catdir($self->blib, $_), $_],
  2671.                 qw( script lib );
  2672.  
  2673.   foreach my $pod ( keys %$pods ) {
  2674.  
  2675.     my ($name, $path) = File::Basename::fileparse($pods->{$pod},
  2676.                                                  file_qr('\.(?:pm|plx?|pod)$'));
  2677.     my @dirs = File::Spec->splitdir( File::Spec->canonpath( $path ) );
  2678.     pop( @dirs ) if $dirs[-1] eq File::Spec->curdir;
  2679.  
  2680.     my $fulldir = File::Spec->catfile($htmldir, @rootdirs, @dirs);
  2681.     my $outfile = File::Spec->catfile($fulldir, "${name}.html");
  2682.     my $infile  = File::Spec->abs2rel($pod);
  2683.  
  2684.     next if $self->up_to_date($infile, $outfile);
  2685.  
  2686.     unless ( -d $fulldir ){
  2687.       File::Path::mkpath($fulldir, 0, oct(755))
  2688.         or die "Couldn't mkdir $fulldir: $!";
  2689.     }
  2690.  
  2691.     my $path2root = join( '/', ('..') x (@rootdirs+@dirs) );
  2692.     my $htmlroot = join( '/',
  2693.              ($path2root,
  2694.               $self->installdirs eq 'core' ? () : qw(site) ) );
  2695.  
  2696.     my $fh = IO::File->new($infile) or die "Can't read $infile: $!";
  2697.     my $abstract = Module::Build::PodParser->new(fh => $fh)->get_abstract();
  2698.  
  2699.     my $title = join( '::', (@dirs, $name) );
  2700.     $title .= " - $abstract" if $abstract;
  2701.  
  2702.     my @opts = (
  2703.                 '--flush',
  2704.                 "--title=$title",
  2705.                 "--podpath=$podpath",
  2706.                 "--infile=$infile",
  2707.                 "--outfile=$outfile",
  2708.                 '--podroot=' . $self->blib,
  2709.                 "--htmlroot=$htmlroot",
  2710.                );
  2711.  
  2712.     if ( eval{Pod::Html->VERSION(1.03)} ) {
  2713.       push( @opts, ('--header', '--backlink=Back to Top') );
  2714.       push( @opts, "--css=$path2root/" . $self->html_css) if $self->html_css;
  2715.     }
  2716.  
  2717.     $self->log_info("HTMLifying $infile -> $outfile\n");
  2718.     $self->log_verbose("pod2html @opts\n");
  2719.     Pod::Html::pod2html(@opts);    # or warn "pod2html @opts failed: $!";
  2720.   }
  2721.  
  2722. }
  2723.  
  2724. # Adapted from ExtUtils::MM_Unix
  2725. sub man1page_name {
  2726.   my $self = shift;
  2727.   return File::Basename::basename( shift );
  2728. }
  2729.  
  2730. # Adapted from ExtUtils::MM_Unix and Pod::Man
  2731. # Depending on M::B's dependency policy, it might make more sense to refactor
  2732. # Pod::Man::begin_pod() to extract a name() methods, and use them...
  2733. #    -spurkis
  2734. sub man3page_name {
  2735.   my $self = shift;
  2736.   my ($vol, $dirs, $file) = File::Spec->splitpath( shift );
  2737.   my @dirs = File::Spec->splitdir( File::Spec->canonpath($dirs) );
  2738.   
  2739.   # Remove known exts from the base name
  2740.   $file =~ s/\.p(?:od|m|l)\z//i;
  2741.   
  2742.   return join( $self->manpage_separator, @dirs, $file );
  2743. }
  2744.  
  2745. sub manpage_separator {
  2746.   return '::';
  2747. }
  2748.  
  2749. # For systems that don't have 'diff' executable, should use Algorithm::Diff
  2750. sub ACTION_diff {
  2751.   my $self = shift;
  2752.   $self->depends_on('build');
  2753.   my $local_lib = File::Spec->rel2abs('lib');
  2754.   my @myINC = grep {$_ ne $local_lib} @INC;
  2755.  
  2756.   # The actual install destination might not be in @INC, so check there too.
  2757.   push @myINC, map $self->install_destination($_), qw(lib arch);
  2758.  
  2759.   my @flags = @{$self->{args}{ARGV}};
  2760.   @flags = $self->split_like_shell($self->{args}{flags} || '') unless @flags;
  2761.   
  2762.   my $installmap = $self->install_map;
  2763.   delete $installmap->{read};
  2764.   delete $installmap->{write};
  2765.  
  2766.   my $text_suffix = file_qr('\.(pm|pod)$');
  2767.  
  2768.   while (my $localdir = each %$installmap) {
  2769.     my @localparts = File::Spec->splitdir($localdir);
  2770.     my $files = $self->rscan_dir($localdir, sub {-f});
  2771.     
  2772.     foreach my $file (@$files) {
  2773.       my @parts = File::Spec->splitdir($file);
  2774.       @parts = @parts[@localparts .. $#parts]; # Get rid of blib/lib or similar
  2775.       
  2776.       my $installed = Module::Build::ModuleInfo->find_module_by_name(
  2777.                         join('::', @parts), \@myINC );
  2778.       if (not $installed) {
  2779.     print "Only in lib: $file\n";
  2780.     next;
  2781.       }
  2782.       
  2783.       my $status = File::Compare::compare($installed, $file);
  2784.       next if $status == 0;  # Files are the same
  2785.       die "Can't compare $installed and $file: $!" if $status == -1;
  2786.       
  2787.       if ($file =~ $text_suffix) {
  2788.     $self->do_system('diff', @flags, $installed, $file);
  2789.       } else {
  2790.     print "Binary files $file and $installed differ\n";
  2791.       }
  2792.     }
  2793.   }
  2794. }
  2795.  
  2796. sub ACTION_pure_install {
  2797.   shift()->depends_on('install');
  2798. }
  2799.  
  2800. sub ACTION_install {
  2801.   my ($self) = @_;
  2802.   require ExtUtils::Install;
  2803.   $self->depends_on('build');
  2804.   ExtUtils::Install::install($self->install_map, !$self->quiet, 0, $self->{args}{uninst}||0);
  2805. }
  2806.  
  2807. sub ACTION_fakeinstall {
  2808.   my ($self) = @_;
  2809.   require ExtUtils::Install;
  2810.   $self->depends_on('build');
  2811.   ExtUtils::Install::install($self->install_map, !$self->quiet, 1, $self->{args}{uninst}||0);
  2812. }
  2813.  
  2814. sub ACTION_versioninstall {
  2815.   my ($self) = @_;
  2816.   
  2817.   die "You must have only.pm 0.25 or greater installed for this operation: $@\n"
  2818.     unless eval { require only; 'only'->VERSION(0.25); 1 };
  2819.   
  2820.   $self->depends_on('build');
  2821.   
  2822.   my %onlyargs = map {exists($self->{args}{$_}) ? ($_ => $self->{args}{$_}) : ()}
  2823.     qw(version versionlib);
  2824.   only::install::install(%onlyargs);
  2825. }
  2826.  
  2827. sub ACTION_clean {
  2828.   my ($self) = @_;
  2829.   foreach my $item (map glob($_), $self->cleanup) {
  2830.     $self->delete_filetree($item);
  2831.   }
  2832. }
  2833.  
  2834. sub ACTION_realclean {
  2835.   my ($self) = @_;
  2836.   $self->depends_on('clean');
  2837.   $self->delete_filetree($self->config_dir, $self->build_script);
  2838. }
  2839.  
  2840. sub ACTION_ppd {
  2841.   my ($self) = @_;
  2842.   require Module::Build::PPMMaker;
  2843.   my $ppd = Module::Build::PPMMaker->new();
  2844.   my $file = $ppd->make_ppd(%{$self->{args}}, build => $self);
  2845.   $self->add_to_cleanup($file);
  2846. }
  2847.  
  2848. sub ACTION_ppmdist {
  2849.   my ($self) = @_;
  2850.  
  2851.   $self->depends_on( 'build' );
  2852.  
  2853.   my $ppm = $self->ppm_name;
  2854.   $self->delete_filetree( $ppm );
  2855.   $self->log_info( "Creating $ppm\n" );
  2856.   $self->add_to_cleanup( $ppm, "$ppm.tar.gz" );
  2857.  
  2858.   my %types = ( # translate types/dirs to those expected by ppm
  2859.     lib     => 'lib',
  2860.     arch    => 'arch',
  2861.     bin     => 'bin',
  2862.     script  => 'script',
  2863.     bindoc  => 'man1',
  2864.     libdoc  => 'man3',
  2865.     binhtml => undef,
  2866.     libhtml => undef,
  2867.   );
  2868.  
  2869.   foreach my $type ($self->install_types) {
  2870.     next if exists( $types{$type} ) && !defined( $types{$type} );
  2871.  
  2872.     my $dir = File::Spec->catdir( $self->blib, $type );
  2873.     next unless -e $dir;
  2874.  
  2875.     my $files = $self->rscan_dir( $dir );
  2876.     foreach my $file ( @$files ) {
  2877.       next unless -f $file;
  2878.       my $rel_file =
  2879.     File::Spec->abs2rel( File::Spec->rel2abs( $file ),
  2880.                  File::Spec->rel2abs( $dir  ) );
  2881.       my $to_file  =
  2882.     File::Spec->catdir( $ppm, 'blib',
  2883.                 exists( $types{$type} ) ? $types{$type} : $type,
  2884.                 $rel_file );
  2885.       $self->copy_if_modified( from => $file, to => $to_file );
  2886.     }
  2887.   }
  2888.  
  2889.   foreach my $type ( qw(bin lib) ) {
  2890.     local $self->{properties}{html_css} = 'Active.css';
  2891.     $self->htmlify_pods( $type, File::Spec->catdir($ppm, 'blib', 'html') );
  2892.   }
  2893.  
  2894.   # create a tarball;
  2895.   # the directory tar'ed must be blib so we need to do a chdir first
  2896.   my $target = File::Spec->catfile( File::Spec->updir, $ppm );
  2897.   $self->_do_in_dir( $ppm, sub { $self->make_tarball( 'blib', $target ) } );
  2898.  
  2899.   $self->depends_on( 'ppd' );
  2900.  
  2901.   $self->delete_filetree( $ppm );
  2902. }
  2903.  
  2904. sub ACTION_pardist {
  2905.   my ($self) = @_;
  2906.  
  2907.   # Need PAR::Dist
  2908.   if ( not eval { require PAR::Dist; PAR::Dist->VERSION(0.17) } ) {
  2909.     $self->log_warn(
  2910.       "In order to create .par distributions, you need to\n"
  2911.       . "install PAR::Dist first."
  2912.     );
  2913.     return();
  2914.   }
  2915.   
  2916.   $self->depends_on( 'build' );
  2917.  
  2918.   return PAR::Dist::blib_to_par(
  2919.     name => $self->dist_name,
  2920.     version => $self->dist_version,
  2921.   );
  2922. }
  2923.  
  2924. sub ACTION_dist {
  2925.   my ($self) = @_;
  2926.   
  2927.   $self->depends_on('distdir');
  2928.   
  2929.   my $dist_dir = $self->dist_dir;
  2930.   
  2931.   $self->make_tarball($dist_dir);
  2932.   $self->delete_filetree($dist_dir);
  2933. }
  2934.  
  2935. sub ACTION_distcheck {
  2936.   my ($self) = @_;
  2937.  
  2938.   require ExtUtils::Manifest;
  2939.   local $^W; # ExtUtils::Manifest is not warnings clean.
  2940.   my ($missing, $extra) = ExtUtils::Manifest::fullcheck();
  2941.  
  2942.   return unless @$missing || @$extra;
  2943.  
  2944.   my $msg = "MANIFEST appears to be out of sync with the distribution\n";
  2945.   if ( $self->invoked_action eq 'distcheck' ) {
  2946.     die $msg;
  2947.   } else {
  2948.     warn $msg;
  2949.   }
  2950. }
  2951.  
  2952. sub _add_to_manifest {
  2953.   my ($self, $manifest, $lines) = @_;
  2954.   $lines = [$lines] unless ref $lines;
  2955.  
  2956.   my $existing_files = $self->_read_manifest($manifest);
  2957.   return unless defined( $existing_files );
  2958.  
  2959.   @$lines = grep {!exists $existing_files->{$_}} @$lines
  2960.     or return;
  2961.  
  2962.   my $mode = (stat $manifest)[2];
  2963.   chmod($mode | oct(222), $manifest) or die "Can't make $manifest writable: $!";
  2964.   
  2965.   my $fh = IO::File->new("< $manifest") or die "Can't read $manifest: $!";
  2966.   my $last_line = (<$fh>)[-1] || "\n";
  2967.   my $has_newline = $last_line =~ /\n$/;
  2968.   $fh->close;
  2969.  
  2970.   $fh = IO::File->new(">> $manifest") or die "Can't write to $manifest: $!";
  2971.   print $fh "\n" unless $has_newline;
  2972.   print $fh map "$_\n", @$lines;
  2973.   close $fh;
  2974.   chmod($mode, $manifest);
  2975.  
  2976.   $self->log_info(map "Added to $manifest: $_\n", @$lines);
  2977. }
  2978.  
  2979. sub _sign_dir {
  2980.   my ($self, $dir) = @_;
  2981.  
  2982.   unless (eval { require Module::Signature; 1 }) {
  2983.     $self->log_warn("Couldn't load Module::Signature for 'distsign' action:\n $@\n");
  2984.     return;
  2985.   }
  2986.   
  2987.   # Add SIGNATURE to the MANIFEST
  2988.   {
  2989.     my $manifest = File::Spec->catfile($dir, 'MANIFEST');
  2990.     die "Signing a distribution requires a MANIFEST file" unless -e $manifest;
  2991.     $self->_add_to_manifest($manifest, "SIGNATURE    Added here by Module::Build");
  2992.   }
  2993.   
  2994.   # Would be nice if Module::Signature took a directory argument.
  2995.   
  2996.   $self->_do_in_dir($dir, sub {local $Module::Signature::Quiet = 1; Module::Signature::sign()});
  2997. }
  2998.  
  2999. sub _do_in_dir {
  3000.   my ($self, $dir, $do) = @_;
  3001.  
  3002.   my $start_dir = $self->cwd;
  3003.   chdir $dir or die "Can't chdir() to $dir: $!";
  3004.   eval {$do->()};
  3005.   my @err = $@ ? ($@) : ();
  3006.   chdir $start_dir or push @err, "Can't chdir() back to $start_dir: $!";
  3007.   die join "\n", @err if @err;
  3008. }
  3009.  
  3010. sub ACTION_distsign {
  3011.   my ($self) = @_;
  3012.   {
  3013.     local $self->{properties}{sign} = 0;  # We'll sign it ourselves
  3014.     $self->depends_on('distdir') unless -d $self->dist_dir;
  3015.   }
  3016.   $self->_sign_dir($self->dist_dir);
  3017. }
  3018.  
  3019. sub ACTION_skipcheck {
  3020.   my ($self) = @_;
  3021.   
  3022.   require ExtUtils::Manifest;
  3023.   local $^W; # ExtUtils::Manifest is not warnings clean.
  3024.   ExtUtils::Manifest::skipcheck();
  3025. }
  3026.  
  3027. sub ACTION_distclean {
  3028.   my ($self) = @_;
  3029.   
  3030.   $self->depends_on('realclean');
  3031.   $self->depends_on('distcheck');
  3032. }
  3033.  
  3034. sub do_create_makefile_pl {
  3035.   my $self = shift;
  3036.   require Module::Build::Compat;
  3037.   $self->delete_filetree('Makefile.PL');
  3038.   $self->log_info("Creating Makefile.PL\n");
  3039.   Module::Build::Compat->create_makefile_pl($self->create_makefile_pl, $self, @_);
  3040.   $self->_add_to_manifest('MANIFEST', 'Makefile.PL');
  3041. }
  3042.  
  3043. sub do_create_readme {
  3044.   my $self = shift;
  3045.   $self->delete_filetree('README');
  3046.  
  3047.   my $docfile = $self->_main_docfile;
  3048.   unless ( $docfile ) {
  3049.     $self->log_warn(<<EOF);
  3050. Cannot create README: can't determine which file contains documentation;
  3051. Must supply either 'dist_version_from', or 'module_name' parameter.
  3052. EOF
  3053.     return;
  3054.   }
  3055.  
  3056.   if ( eval {require Pod::Readme; 1} ) {
  3057.     $self->log_info("Creating README using Pod::Readme\n");
  3058.  
  3059.     my $parser = Pod::Readme->new;
  3060.     $parser->parse_from_file($docfile, 'README', @_);
  3061.  
  3062.   } elsif ( eval {require Pod::Text; 1} ) {
  3063.     $self->log_info("Creating README using Pod::Text\n");
  3064.  
  3065.     my $fh = IO::File->new('> README');
  3066.     if ( defined($fh) ) {
  3067.       local $^W = 0;
  3068.       no strict "refs";
  3069.  
  3070.       # work around bug in Pod::Text 3.01, which expects
  3071.       # Pod::Simple::parse_file to take input and output filehandles
  3072.       # when it actually only takes an input filehandle
  3073.  
  3074.       my $old_parse_file;
  3075.       $old_parse_file = \&{"Pod::Simple::parse_file"}
  3076.     and
  3077.       local *{"Pod::Simple::parse_file"} = sub {
  3078.     my $self = shift;
  3079.     $self->output_fh($_[1]) if $_[1];
  3080.     $self->$old_parse_file($_[0]);
  3081.       }
  3082.         if $Pod::Text::VERSION
  3083.       == 3.01; # Split line to avoid evil version-finder
  3084.  
  3085.       Pod::Text::pod2text( $docfile, $fh );
  3086.  
  3087.       $fh->close;
  3088.     } else {
  3089.       $self->log_warn(
  3090.         "Cannot create 'README' file: Can't open file for writing\n" );
  3091.       return;
  3092.     }
  3093.  
  3094.   } else {
  3095.     $self->log_warn("Can't load Pod::Readme or Pod::Text to create README\n");
  3096.     return;
  3097.   }
  3098.  
  3099.   $self->_add_to_manifest('MANIFEST', 'README');
  3100. }
  3101.  
  3102. sub _main_docfile {
  3103.   my $self = shift;
  3104.   if ( my $pm_file = $self->dist_version_from ) {
  3105.     (my $pod_file = $pm_file) =~ s/.pm$/.pod/;
  3106.     return (-e $pod_file ? $pod_file : $pm_file);
  3107.   } else {
  3108.     return undef;
  3109.   }
  3110. }
  3111.  
  3112. sub ACTION_distdir {
  3113.   my ($self) = @_;
  3114.  
  3115.   $self->depends_on('distmeta');
  3116.  
  3117.   my $dist_files = $self->_read_manifest('MANIFEST')
  3118.     or die "Can't create distdir without a MANIFEST file - run 'manifest' action first";
  3119.   delete $dist_files->{SIGNATURE};  # Don't copy, create a fresh one
  3120.   die "No files found in MANIFEST - try running 'manifest' action?\n"
  3121.     unless ($dist_files and keys %$dist_files);
  3122.   my $metafile = $self->metafile;
  3123.   $self->log_warn("*** Did you forget to add $metafile to the MANIFEST?\n")
  3124.     unless exists $dist_files->{$metafile};
  3125.   
  3126.   my $dist_dir = $self->dist_dir;
  3127.   $self->delete_filetree($dist_dir);
  3128.   $self->log_info("Creating $dist_dir\n");
  3129.   $self->add_to_cleanup($dist_dir);
  3130.   
  3131.   foreach my $file (keys %$dist_files) {
  3132.     my $new = $self->copy_if_modified(from => $file, to_dir => $dist_dir, verbose => 0);
  3133.   }
  3134.   
  3135.   $self->_sign_dir($dist_dir) if $self->{properties}{sign};
  3136. }
  3137.  
  3138. sub ACTION_disttest {
  3139.   my ($self) = @_;
  3140.  
  3141.   $self->depends_on('distdir');
  3142.  
  3143.   $self->_do_in_dir
  3144.     ( $self->dist_dir,
  3145.       sub {
  3146.     # XXX could be different names for scripts
  3147.  
  3148.     $self->run_perl_script('Build.PL') # XXX Should this be run w/ --nouse-rcfile
  3149.       or die "Error executing 'Build.PL' in dist directory: $!";
  3150.     $self->run_perl_script('Build')
  3151.       or die "Error executing 'Build' in dist directory: $!";
  3152.     $self->run_perl_script('Build', [], ['test'])
  3153.       or die "Error executing 'Build test' in dist directory";
  3154.       });
  3155. }
  3156.  
  3157. sub _write_default_maniskip {
  3158.   my $self = shift;
  3159.   my $file = shift || 'MANIFEST.SKIP';
  3160.   my $fh = IO::File->new("> $file")
  3161.     or die "Can't open $file: $!";
  3162.  
  3163.   # This is derived from MakeMaker's default MANIFEST.SKIP file with
  3164.   # some new entries
  3165.  
  3166.   print $fh <<'EOF';
  3167. # Avoid version control files.
  3168. \bRCS\b
  3169. \bCVS\b
  3170. ,v$
  3171. \B\.svn\b
  3172. \B\.cvsignore$
  3173.  
  3174. # Avoid Makemaker generated and utility files.
  3175. \bMakefile$
  3176. \bblib
  3177. \bMakeMaker-\d
  3178. \bpm_to_blib$
  3179. \bblibdirs$
  3180. ^MANIFEST\.SKIP$
  3181.  
  3182. # Avoid Module::Build generated and utility files.
  3183. \bBuild$
  3184. \bBuild.bat$
  3185. \b_build
  3186.  
  3187. # Avoid Devel::Cover generated files
  3188. \bcover_db
  3189.  
  3190. # Avoid temp and backup files.
  3191. ~$
  3192. \.tmp$
  3193. \.old$
  3194. \.bak$
  3195. \#$
  3196. \.#
  3197. \.rej$
  3198.  
  3199. # Avoid OS-specific files/dirs
  3200. #   Mac OSX metadata
  3201. \B\.DS_Store
  3202. #   Mac OSX SMB mount metadata files
  3203. \B\._
  3204. # Avoid archives of this distribution
  3205. EOF
  3206.  
  3207.   # Skip, for example, 'Module-Build-0.27.tar.gz'
  3208.   print $fh '\b'.$self->dist_name.'-[\d\.\_]+'."\n";
  3209.  
  3210.   $fh->close();
  3211. }
  3212.  
  3213. sub ACTION_manifest {
  3214.   my ($self) = @_;
  3215.  
  3216.   my $maniskip = 'MANIFEST.SKIP';
  3217.   unless ( -e 'MANIFEST' || -e $maniskip ) {
  3218.     $self->log_warn("File '$maniskip' does not exist: Creating a default '$maniskip'\n");
  3219.     $self->_write_default_maniskip($maniskip);
  3220.   }
  3221.  
  3222.   require ExtUtils::Manifest;  # ExtUtils::Manifest is not warnings clean.
  3223.   local ($^W, $ExtUtils::Manifest::Quiet) = (0,1);
  3224.   ExtUtils::Manifest::mkmanifest();
  3225. }
  3226.  
  3227. # Case insenstive regex for files
  3228. sub file_qr {
  3229.     return File::Spec->case_tolerant ? qr($_[0])i : qr($_[0]);
  3230. }
  3231.  
  3232. sub dist_dir {
  3233.   my ($self) = @_;
  3234.   return "$self->{properties}{dist_name}-$self->{properties}{dist_version}";
  3235. }
  3236.  
  3237. sub ppm_name {
  3238.   my $self = shift;
  3239.   return 'PPM-' . $self->dist_dir;
  3240. }
  3241.  
  3242. sub _files_in {
  3243.   my ($self, $dir) = @_;
  3244.   return unless -d $dir;
  3245.  
  3246.   local *DH;
  3247.   opendir DH, $dir or die "Can't read directory $dir: $!";
  3248.  
  3249.   my @files;
  3250.   while (defined (my $file = readdir DH)) {
  3251.     my $full_path = File::Spec->catfile($dir, $file);
  3252.     next if -d $full_path;
  3253.     push @files, $full_path;
  3254.   }
  3255.   return @files;
  3256. }
  3257.  
  3258. sub script_files {
  3259.   my $self = shift;
  3260.   
  3261.   for ($self->{properties}{script_files}) {
  3262.     $_ = shift if @_;
  3263.     next unless $_;
  3264.     
  3265.     # Always coerce into a hash
  3266.     return $_ if UNIVERSAL::isa($_, 'HASH');
  3267.     return $_ = { map {$_,1} @$_ } if UNIVERSAL::isa($_, 'ARRAY');
  3268.     
  3269.     die "'script_files' must be a hashref, arrayref, or string" if ref();
  3270.     
  3271.     return $_ = { map {$_,1} $self->_files_in( $_ ) } if -d $_;
  3272.     return $_ = {$_ => 1};
  3273.   }
  3274.   
  3275.   return $_ = { map {$_,1} $self->_files_in('bin') };
  3276. }
  3277. BEGIN { *scripts = \&script_files; }
  3278.  
  3279. {
  3280.   my %licenses = (
  3281.     perl         => 'http://dev.perl.org/licenses/',
  3282.     apache       => 'http://apache.org/licenses/LICENSE-2.0',
  3283.     artistic     => 'http://opensource.org/licenses/artistic-license.php',
  3284.     artistic_2   => 'http://opensource.org/licenses/artistic-license-2.0.php',
  3285.     lgpl         => 'http://opensource.org/licenses/lgpl-license.php',
  3286.     bsd          => 'http://opensource.org/licenses/bsd-license.php',
  3287.     gpl          => 'http://opensource.org/licenses/gpl-license.php',
  3288.     mit          => 'http://opensource.org/licenses/mit-license.php',
  3289.     mozilla      => 'http://opensource.org/licenses/mozilla1.1.php',
  3290.     open_source  => undef,
  3291.     unrestricted => undef,
  3292.     restrictive  => undef,
  3293.     unknown      => undef,
  3294.   );
  3295.   sub valid_licenses {
  3296.     return \%licenses;
  3297.   }
  3298. }
  3299.  
  3300. sub _hash_merge {
  3301.   my ($self, $h, $k, $v) = @_;
  3302.   if (ref $h->{$k} eq 'ARRAY') {
  3303.     push @{$h->{$k}}, ref $v ? @$v : $v;
  3304.   } elsif (ref $h->{$k} eq 'HASH') {
  3305.     $h->{$k}{$_} = $v->{$_} foreach keys %$v;
  3306.   } else {
  3307.     $h->{$k} = $v;
  3308.   }
  3309. }
  3310.  
  3311. sub ACTION_distmeta {
  3312.   my ($self) = @_;
  3313.  
  3314.   $self->do_create_makefile_pl if $self->create_makefile_pl;
  3315.   $self->do_create_readme if $self->create_readme;
  3316.   $self->do_create_metafile;
  3317. }
  3318.  
  3319. sub do_create_metafile {
  3320.   my $self = shift;
  3321.   return if $self->{wrote_metadata};
  3322.   
  3323.   my $p = $self->{properties};
  3324.   my $metafile = $self->metafile;
  3325.   
  3326.   unless ($p->{license}) {
  3327.     $self->log_warn("No license specified, setting license = 'unknown'\n");
  3328.     $p->{license} = 'unknown';
  3329.   }
  3330.   unless (exists $self->valid_licenses->{ $p->{license} }) {
  3331.     die "Unknown license type '$p->{license}'";
  3332.   }
  3333.  
  3334.   # If we're in the distdir, the metafile may exist and be non-writable.
  3335.   $self->delete_filetree($metafile);
  3336.   $self->log_info("Creating $metafile\n");
  3337.  
  3338.   # Since we're building ourself, we have to do some special stuff
  3339.   # here: the ConfigData module is found in blib/lib.
  3340.   local @INC = @INC;
  3341.   if (($self->module_name || '') eq 'Module::Build') {
  3342.     $self->depends_on('config_data');
  3343.     push @INC, File::Spec->catdir($self->blib, 'lib');
  3344.   }
  3345.  
  3346.   $self->write_metafile;
  3347. }
  3348.  
  3349. sub write_metafile {
  3350.   my $self = shift;
  3351.   my $metafile = $self->metafile;
  3352.  
  3353.   if ($self->_mb_feature('YAML_support')) {
  3354.     require YAML;
  3355.     require YAML::Node;
  3356.  
  3357.     # We use YAML::Node to get the order nice in the YAML file.
  3358.     $self->prepare_metadata( my $node = YAML::Node->new({}) );
  3359.     
  3360.     # YAML API changed after version 0.30
  3361.     my $yaml_sub = $YAML::VERSION le '0.30' ? \&YAML::StoreFile : \&YAML::DumpFile;
  3362.     $self->{wrote_metadata} = $yaml_sub->($metafile, $node );
  3363.  
  3364.   } else {
  3365.     require Module::Build::YAML;
  3366.     my (%node, @order_keys);
  3367.     $self->prepare_metadata(\%node, \@order_keys);
  3368.     $node{_order} = \@order_keys;
  3369.     &Module::Build::YAML::DumpFile($metafile, \%node);
  3370.     $self->{wrote_metadata} = 1;
  3371.   }
  3372.  
  3373.   $self->_add_to_manifest('MANIFEST', $metafile);
  3374. }
  3375.  
  3376. sub prepare_metadata {
  3377.   my ($self, $node, $keys) = @_;
  3378.   my $p = $self->{properties};
  3379.  
  3380.   # A little helper sub
  3381.   my $add_node = sub {
  3382.     my ($name, $val) = @_;
  3383.     $node->{$name} = $val;
  3384.     push @$keys, $name if $keys;
  3385.   };
  3386.  
  3387.   foreach (qw(dist_name dist_version dist_author dist_abstract license)) {
  3388.     (my $name = $_) =~ s/^dist_//;
  3389.     $add_node->($name, $self->$_());
  3390.     die "ERROR: Missing required field '$_' for META.yml\n"
  3391.       unless defined($node->{$name}) && length($node->{$name});
  3392.   }
  3393.   $node->{version} = '' . $node->{version}; # Stringify version objects
  3394.  
  3395.   if (defined( $self->license ) &&
  3396.       defined( my $url = $self->valid_licenses->{ $self->license } )) {
  3397.     $node->{resources}{license} = $url;
  3398.   }
  3399.  
  3400.   if (exists $p->{configure_requires}) {
  3401.     foreach my $spec (keys %{$p->{configure_requires}}) {
  3402.       warn ("Warning: $spec is listed in 'configure_requires', but ".
  3403.         "it is not found in any of the other prereq fields.\n")
  3404.     unless grep exists $p->{$_}{$spec}, 
  3405.            grep !/conflicts$/, @{$self->prereq_action_types};
  3406.     }
  3407.   }
  3408.  
  3409.   foreach ( 'configure_requires', @{$self->prereq_action_types} ) {
  3410.     if (exists $p->{$_} and keys %{ $p->{$_} }) {
  3411.       $add_node->($_, $p->{$_});
  3412.     }
  3413.   }
  3414.  
  3415.   if (exists $p->{dynamic_config}) {
  3416.     $add_node->('dynamic_config', $p->{dynamic_config});
  3417.   }
  3418.   my $pkgs = eval { $self->find_dist_packages };
  3419.   if ($@) {
  3420.     $self->log_warn("$@\nWARNING: Possible missing or corrupt 'MANIFEST' file.\n" .
  3421.             "Nothing to enter for 'provides' field in META.yml\n");
  3422.   } else {
  3423.     $node->{provides} = $pkgs if %$pkgs;
  3424.   }
  3425. ;
  3426.   if (exists $p->{no_index}) {
  3427.     $add_node->('no_index', $p->{no_index});
  3428.   }
  3429.  
  3430.   $add_node->('generated_by', "Module::Build version $Module::Build::VERSION");
  3431.  
  3432.   $add_node->('meta-spec', 
  3433.           {version => '1.2',
  3434.            url     => 'http://module-build.sourceforge.net/META-spec-v1.2.html',
  3435.           });
  3436.  
  3437.   while (my($k, $v) = each %{$self->meta_add}) {
  3438.     $add_node->($k, $v);
  3439.   }
  3440.  
  3441.   while (my($k, $v) = each %{$self->meta_merge}) {
  3442.     $self->_hash_merge($node, $k, $v);
  3443.   }
  3444.  
  3445.   return $node;
  3446. }
  3447.  
  3448. sub _read_manifest {
  3449.   my ($self, $file) = @_;
  3450.   return undef unless -e $file;
  3451.  
  3452.   require ExtUtils::Manifest;  # ExtUtils::Manifest is not warnings clean.
  3453.   local ($^W, $ExtUtils::Manifest::Quiet) = (0,1);
  3454.   return scalar ExtUtils::Manifest::maniread($file);
  3455. }
  3456.  
  3457. sub find_dist_packages {
  3458.   my $self = shift;
  3459.  
  3460.   # Only packages in .pm files are candidates for inclusion here.
  3461.   # Only include things in the MANIFEST, not things in developer's
  3462.   # private stock.
  3463.  
  3464.   my $manifest = $self->_read_manifest('MANIFEST')
  3465.     or die "Can't find dist packages without a MANIFEST file - run 'manifest' action first";
  3466.  
  3467.   # Localize
  3468.   my %dist_files = map { $self->localize_file_path($_) => $_ }
  3469.                        keys %$manifest;
  3470.  
  3471.   my @pm_files = grep {exists $dist_files{$_}} keys %{ $self->find_pm_files };
  3472.  
  3473.   # First, we enumerate all packages & versions,
  3474.   # seperating into primary & alternative candidates
  3475.   my( %prime, %alt );
  3476.   foreach my $file (@pm_files) {
  3477.     next if $dist_files{$file} =~ m{^t/};  # Skip things in t/
  3478.  
  3479.     my @path = split( /\//, $dist_files{$file} );
  3480.     (my $prime_package = join( '::', @path[1..$#path] )) =~ s/\.pm$//;
  3481.  
  3482.     my $pm_info = Module::Build::ModuleInfo->new_from_file( $file );
  3483.  
  3484.     foreach my $package ( $pm_info->packages_inside ) {
  3485.       next if $package eq 'main';  # main can appear numerous times, ignore
  3486.       next if grep /^_/, split( /::/, $package ); # private package, ignore
  3487.  
  3488.       my $version = $pm_info->version( $package );
  3489.  
  3490.       if ( $package eq $prime_package ) {
  3491.     if ( exists( $prime{$package} ) ) {
  3492.       # M::B::ModuleInfo will handle this conflict
  3493.       die "Unexpected conflict in '$package'; multiple versions found.\n";
  3494.     } else {
  3495.       $prime{$package}{file} = $dist_files{$file};
  3496.           $prime{$package}{version} = $version if defined( $version );
  3497.         }
  3498.       } else {
  3499.     push( @{$alt{$package}}, {
  3500.                   file    => $dist_files{$file},
  3501.                   version => $version,
  3502.                      } );
  3503.       }
  3504.     }
  3505.   }
  3506.  
  3507.   # Then we iterate over all the packages found above, identifying conflicts
  3508.   # and selecting the "best" candidate for recording the file & version
  3509.   # for each package.
  3510.   foreach my $package ( keys( %alt ) ) {
  3511.     my $result = $self->_resolve_module_versions( $alt{$package} );
  3512.  
  3513.     if ( exists( $prime{$package} ) ) { # primary package selected
  3514.  
  3515.       if ( $result->{err} ) {
  3516.     # Use the selected primary package, but there are conflicting
  3517.     # errors amoung multiple alternative packages that need to be
  3518.     # reported
  3519.         $self->log_warn(
  3520.       "Found conflicting versions for package '$package'\n" .
  3521.       "  $prime{$package}{file} ($prime{$package}{version})\n" .
  3522.       $result->{err}
  3523.         );
  3524.  
  3525.       } elsif ( defined( $result->{version} ) ) {
  3526.     # There is a primary package selected, and exactly one
  3527.     # alternative package
  3528.  
  3529.     if ( exists( $prime{$package}{version} ) &&
  3530.          defined( $prime{$package}{version} ) ) {
  3531.       # Unless the version of the primary package agrees with the
  3532.       # version of the alternative package, report a conflict
  3533.       if ( $self->compare_versions( $prime{$package}{version}, '!=',
  3534.                     $result->{version} ) ) {
  3535.             $self->log_warn(
  3536.               "Found conflicting versions for package '$package'\n" .
  3537.           "  $prime{$package}{file} ($prime{$package}{version})\n" .
  3538.           "  $result->{file} ($result->{version})\n"
  3539.             );
  3540.       }
  3541.  
  3542.     } else {
  3543.       # The prime package selected has no version so, we choose to
  3544.       # use any alternative package that does have a version
  3545.       $prime{$package}{file}    = $result->{file};
  3546.       $prime{$package}{version} = $result->{version};
  3547.     }
  3548.  
  3549.       } else {
  3550.     # no alt package found with a version, but we have a prime
  3551.     # package so we use it whether it has a version or not
  3552.       }
  3553.  
  3554.     } else { # No primary package was selected, use the best alternative
  3555.  
  3556.       if ( $result->{err} ) {
  3557.         $self->log_warn(
  3558.           "Found conflicting versions for package '$package'\n" .
  3559.       $result->{err}
  3560.         );
  3561.       }
  3562.  
  3563.       # Despite possible conflicting versions, we choose to record
  3564.       # something rather than nothing
  3565.       $prime{$package}{file}    = $result->{file};
  3566.       $prime{$package}{version} = $result->{version}
  3567.       if defined( $result->{version} );
  3568.     }
  3569.   }
  3570.  
  3571.   # Stringify versions.  Can't use exists() here because of bug in YAML::Node.
  3572.   for (grep defined $_->{version}, values %prime) {
  3573.     $_->{version} = '' . $_->{version};
  3574.   }
  3575.  
  3576.   return \%prime;
  3577. }
  3578.  
  3579. # seperate out some of the conflict resolution logic from
  3580. # $self->find_dist_packages(), above, into a helper function.
  3581. #
  3582. sub _resolve_module_versions {
  3583.   my $self = shift;
  3584.  
  3585.   my $packages = shift;
  3586.  
  3587.   my( $file, $version );
  3588.   my $err = '';
  3589.     foreach my $p ( @$packages ) {
  3590.       if ( defined( $p->{version} ) ) {
  3591.     if ( defined( $version ) ) {
  3592.        if ( $self->compare_versions( $version, '!=', $p->{version} ) ) {
  3593.         $err .= "  $p->{file} ($p->{version})\n";
  3594.       } else {
  3595.         # same version declared multiple times, ignore
  3596.       }
  3597.     } else {
  3598.       $file    = $p->{file};
  3599.       $version = $p->{version};
  3600.     }
  3601.       }
  3602.       $file ||= $p->{file} if defined( $p->{file} );
  3603.     }
  3604.  
  3605.   if ( $err ) {
  3606.     $err = "  $file ($version)\n" . $err;
  3607.   }
  3608.  
  3609.   my %result = (
  3610.     file    => $file,
  3611.     version => $version,
  3612.     err     => $err
  3613.   );
  3614.  
  3615.   return \%result;
  3616. }
  3617.  
  3618. sub make_tarball {
  3619.   my ($self, $dir, $file) = @_;
  3620.   $file ||= $dir;
  3621.   
  3622.   $self->log_info("Creating $file.tar.gz\n");
  3623.   
  3624.   if ($self->{args}{tar}) {
  3625.     my $tar_flags = $self->verbose ? 'cvf' : 'cf';
  3626.     $self->do_system($self->split_like_shell($self->{args}{tar}), $tar_flags, "$file.tar", $dir);
  3627.     $self->do_system($self->split_like_shell($self->{args}{gzip}), "$file.tar") if $self->{args}{gzip};
  3628.   } else {
  3629.     require Archive::Tar;
  3630.     # Archive::Tar versions >= 1.09 use the following to enable a compatibility
  3631.     # hack so that the resulting archive is compatible with older clients.
  3632.     $Archive::Tar::DO_NOT_USE_PREFIX = 0;
  3633.     my $files = $self->rscan_dir($dir);
  3634.     Archive::Tar->create_archive("$file.tar.gz", 1, @$files);
  3635.   }
  3636. }
  3637.  
  3638. sub install_path {
  3639.   my $self = shift;
  3640.   my( $type, $value ) = ( @_, '<empty>' );
  3641.  
  3642.   Carp::croak( 'Type argument missing' )
  3643.     unless defined( $type );
  3644.  
  3645.   my $map = $self->{properties}{install_path};
  3646.   return $map unless @_;
  3647.  
  3648.   # delete existing value if $value is literal undef()
  3649.   unless ( defined( $value ) ) {
  3650.     delete( $map->{$type} );
  3651.     return undef;
  3652.   }
  3653.  
  3654.   # return existing value if no new $value is given
  3655.   if ( $value eq '<empty>' ) {
  3656.     return undef unless exists $map->{$type};
  3657.     return $map->{$type};
  3658.   }
  3659.  
  3660.   # set value if $value is a valid relative path
  3661.   return $map->{$type} = $value;
  3662. }
  3663.  
  3664. sub install_base_relpaths {
  3665.   # Usage: install_base_relpaths(), install_base_relpaths('lib'),
  3666.   #   or install_base_relpaths('lib' => $value);
  3667.   my $self = shift;
  3668.   my $map = $self->{properties}{install_base_relpaths};
  3669.   return $map unless @_;
  3670.   return $self->_relpaths($map, @_);
  3671. }
  3672.  
  3673.  
  3674. # Translated from ExtUtils::MM_Any::init_INSTALL_from_PREFIX
  3675. sub prefix_relative {
  3676.   my ($self, $type) = @_;
  3677.   my $installdirs = $self->installdirs;
  3678.  
  3679.   my $relpath = $self->install_sets($installdirs)->{$type};
  3680.  
  3681.   return $self->_prefixify($relpath,
  3682.                $self->original_prefix($installdirs),
  3683.                $type,
  3684.               );
  3685. }
  3686.  
  3687. sub _relpaths {
  3688.   my $self = shift;
  3689.   my( $map, $type, $value ) = ( @_, '<empty>' );
  3690.  
  3691.   Carp::croak( 'Type argument missing' )
  3692.     unless defined( $type );
  3693.  
  3694.   my @value = ();
  3695.  
  3696.   # delete existing value if $value is literal undef()
  3697.   unless ( defined( $value ) ) {
  3698.     delete( $map->{$type} );
  3699.     return undef;
  3700.   }
  3701.  
  3702.   # return existing value if no new $value is given
  3703.   elsif ( $value eq '<empty>' ) {
  3704.     return undef unless exists $map->{$type};
  3705.     @value = @{ $map->{$type} };
  3706.   }
  3707.  
  3708.   # set value if $value is a valid relative path
  3709.   else {
  3710.     Carp::croak( "Value must be a relative path" )
  3711.       if File::Spec::Unix->file_name_is_absolute($value);
  3712.  
  3713.     @value = split( /\//, $value );
  3714.     $map->{$type} = \@value;
  3715.   }
  3716.  
  3717.   return File::Spec->catdir( @value );
  3718. }
  3719.  
  3720. # Defaults to use in case the config install paths cannot be prefixified.
  3721. sub prefix_relpaths {
  3722.   # Usage: prefix_relpaths('site'), prefix_relpaths('site', 'lib'),
  3723.   #   or prefix_relpaths('site', 'lib' => $value);
  3724.   my $self = shift;
  3725.   my $installdirs = shift || $self->installdirs;
  3726.   my $map = $self->{properties}{prefix_relpaths}{$installdirs};
  3727.   return $map unless @_;
  3728.   return $self->_relpaths($map, @_);
  3729. }
  3730.  
  3731.  
  3732. # Translated from ExtUtils::MM_Unix::prefixify()
  3733. sub _prefixify {
  3734.   my($self, $path, $sprefix, $type) = @_;
  3735.  
  3736.   my $rprefix = $self->prefix;
  3737.   $rprefix .= '/' if $sprefix =~ m|/$|;
  3738.  
  3739.   $self->log_verbose("  prefixify $path from $sprefix to $rprefix\n")
  3740.     if defined( $path ) && length( $path );
  3741.  
  3742.   if( !defined( $path ) || ( length( $path ) == 0 ) ) {
  3743.     $self->log_verbose("  no path to prefixify, falling back to default.\n");
  3744.     return $self->_prefixify_default( $type, $rprefix );
  3745.   } elsif( !File::Spec->file_name_is_absolute($path) ) {
  3746.     $self->log_verbose("    path is relative, not prefixifying.\n");
  3747.   } elsif( $sprefix eq $rprefix ) {
  3748.     $self->log_verbose("  no new prefix.\n");
  3749.   } elsif( $path !~ s{^\Q$sprefix\E\b}{}s ) {
  3750.     $self->log_verbose("    cannot prefixify, falling back to default.\n");
  3751.     return $self->_prefixify_default( $type, $rprefix );
  3752.   }
  3753.  
  3754.   $self->log_verbose("    now $path in $rprefix\n");
  3755.  
  3756.   return $path;
  3757. }
  3758.  
  3759. sub _prefixify_default {
  3760.   my $self = shift;
  3761.   my $type = shift;
  3762.   my $rprefix = shift;
  3763.  
  3764.   my $default = $self->prefix_relpaths($self->installdirs, $type);
  3765.   if( !$default ) {
  3766.     $self->log_verbose("    no default install location for type '$type', using prefix '$rprefix'.\n");
  3767.     return $rprefix;
  3768.   } else {
  3769.     return $default;
  3770.   }
  3771. }
  3772.  
  3773. sub install_destination {
  3774.   my ($self, $type) = @_;
  3775.  
  3776.   return $self->install_path($type) if $self->install_path($type);
  3777.  
  3778.   if ( $self->install_base ) {
  3779.     my $relpath = $self->install_base_relpaths($type);
  3780.     return $relpath ? File::Spec->catdir($self->install_base, $relpath) : undef;
  3781.   }
  3782.  
  3783.   if ( $self->prefix ) {
  3784.     my $relpath = $self->prefix_relative($type);
  3785.     return $relpath ? File::Spec->catdir($self->prefix, $relpath) : undef;
  3786.   }
  3787.  
  3788.   return $self->install_sets($self->installdirs)->{$type};
  3789. }
  3790.  
  3791. sub install_types {
  3792.   my $self = shift;
  3793.  
  3794.   my %types;
  3795.   if ( $self->install_base ) {
  3796.     %types = %{$self->install_base_relpaths};
  3797.   } elsif ( $self->prefix ) {
  3798.     %types = %{$self->prefix_relpaths};
  3799.   } else {
  3800.     %types = %{$self->install_sets($self->installdirs)};
  3801.   }
  3802.  
  3803.   %types = (%types, %{$self->install_path});
  3804.  
  3805.   return sort keys %types;
  3806. }
  3807.  
  3808. sub install_map {
  3809.   my ($self, $blib) = @_;
  3810.   $blib ||= $self->blib;
  3811.  
  3812.   my( %map, @skipping );
  3813.   foreach my $type ($self->install_types) {
  3814.     my $localdir = File::Spec->catdir( $blib, $type );
  3815.     next unless -e $localdir;
  3816.  
  3817.     if (my $dest = $self->install_destination($type)) {
  3818.       $map{$localdir} = $dest;
  3819.     } else {
  3820.       push( @skipping, $type );
  3821.     }
  3822.   }
  3823.  
  3824.   $self->log_warn(
  3825.     "WARNING: Can't figure out install path for types: @skipping\n" .
  3826.     "Files will not be installed.\n"
  3827.   ) if @skipping;
  3828.  
  3829.   # Write the packlist into the same place as ExtUtils::MakeMaker.
  3830.   if ($self->create_packlist and my $module_name = $self->module_name) {
  3831.     my $archdir = $self->install_destination('arch');
  3832.     my @ext = split /::/, $module_name;
  3833.     $map{write} = File::Spec->catfile($archdir, 'auto', @ext, '.packlist');
  3834.   }
  3835.  
  3836.   # Handle destdir
  3837.   if (length(my $destdir = $self->destdir || '')) {
  3838.     foreach (keys %map) {
  3839.       # Need to remove volume from $map{$_} using splitpath, or else
  3840.       # we'll create something crazy like C:\Foo\Bar\E:\Baz\Quux
  3841.       # VMS will always have the file separate than the path.
  3842.       my ($volume, $path, $file) = File::Spec->splitpath( $map{$_}, 1 );
  3843.  
  3844.       # catdir needs a list of directories, or it will create something
  3845.       # crazy like volume:[Foo.Bar.volume.Baz.Quux]
  3846.       my @dirs = File::Spec->splitdir($path);
  3847.  
  3848.       # First merge the directories
  3849.       $path = File::Spec->catdir($destdir, @dirs);
  3850.  
  3851.       # Then put the file back on if there is one.
  3852.       if ($file ne '') {
  3853.           $map{$_} = File::Spec->catfile($path, $file)
  3854.       } else {
  3855.           $map{$_} = $path;
  3856.       }
  3857.     }
  3858.   }
  3859.   
  3860.   $map{read} = '';  # To keep ExtUtils::Install quiet
  3861.  
  3862.   return \%map;
  3863. }
  3864.  
  3865. sub depends_on {
  3866.   my $self = shift;
  3867.   foreach my $action (@_) {
  3868.     $self->_call_action($action);
  3869.   }
  3870. }
  3871.  
  3872. sub rscan_dir {
  3873.   my ($self, $dir, $pattern) = @_;
  3874.   my @result;
  3875.   local $_; # find() can overwrite $_, so protect ourselves
  3876.   my $subr = !$pattern ? sub {push @result, $File::Find::name} :
  3877.              !ref($pattern) || (ref $pattern eq 'Regexp') ? sub {push @result, $File::Find::name if /$pattern/} :
  3878.          ref($pattern) eq 'CODE' ? sub {push @result, $File::Find::name if $pattern->()} :
  3879.          die "Unknown pattern type";
  3880.   
  3881.   File::Find::find({wanted => $subr, no_chdir => 1}, $dir);
  3882.   return \@result;
  3883. }
  3884.  
  3885. sub delete_filetree {
  3886.   my $self = shift;
  3887.   my $deleted = 0;
  3888.   foreach (@_) {
  3889.     next unless -e $_;
  3890.     $self->log_info("Deleting $_\n");
  3891.     File::Path::rmtree($_, 0, 0);
  3892.     die "Couldn't remove '$_': $!\n" if -e $_;
  3893.     $deleted++;
  3894.   }
  3895.   return $deleted;
  3896. }
  3897.  
  3898. sub autosplit_file {
  3899.   my ($self, $file, $to) = @_;
  3900.   require AutoSplit;
  3901.   my $dir = File::Spec->catdir($to, 'lib', 'auto');
  3902.   AutoSplit::autosplit($file, $dir);
  3903. }
  3904.  
  3905. sub _cbuilder {
  3906.   # Returns a CBuilder object
  3907.  
  3908.   my $self = shift;
  3909.   my $p = $self->{properties};
  3910.   return $p->{_cbuilder} if $p->{_cbuilder};
  3911.   return unless $self->_mb_feature('C_support');
  3912.  
  3913.   require ExtUtils::CBuilder;
  3914.   return $p->{_cbuilder} = ExtUtils::CBuilder->new(config => $self->config);
  3915. }
  3916.  
  3917. sub have_c_compiler {
  3918.   my ($self) = @_;
  3919.   
  3920.   my $p = $self->{properties};
  3921.   return $p->{have_compiler} if defined $p->{have_compiler};
  3922.   
  3923.   $self->log_verbose("Checking if compiler tools configured... ");
  3924.   my $b = $self->_cbuilder;
  3925.   my $have = $b && $b->have_compiler;
  3926.   $self->log_verbose($have ? "ok.\n" : "failed.\n");
  3927.   return $p->{have_compiler} = $have;
  3928. }
  3929.  
  3930. sub compile_c {
  3931.   my ($self, $file, %args) = @_;
  3932.   my $b = $self->_cbuilder
  3933.     or die "Module::Build is not configured with C_support";
  3934.  
  3935.   my $obj_file = $b->object_file($file);
  3936.   $self->add_to_cleanup($obj_file);
  3937.   return $obj_file if $self->up_to_date($file, $obj_file);
  3938.  
  3939.   $b->compile(source => $file,
  3940.           defines => $args{defines},
  3941.           object_file => $obj_file,
  3942.           include_dirs => $self->include_dirs,
  3943.           extra_compiler_flags => $self->extra_compiler_flags,
  3944.          );
  3945.  
  3946.   return $obj_file;
  3947. }
  3948.  
  3949. sub link_c {
  3950.   my ($self, $to, $file_base) = @_;
  3951.   my $p = $self->{properties}; # For convenience
  3952.  
  3953.   my $spec = $self->_infer_xs_spec($file_base);
  3954.  
  3955.   $self->add_to_cleanup($spec->{lib_file});
  3956.  
  3957.   my $objects = $p->{objects} || [];
  3958.  
  3959.   return $spec->{lib_file}
  3960.     if $self->up_to_date([$spec->{obj_file}, @$objects],
  3961.              $spec->{lib_file});
  3962.  
  3963.   my $module_name = $self->module_name;
  3964.   $module_name  ||= $spec->{module_name};
  3965.  
  3966.   my $b = $self->_cbuilder
  3967.     or die "Module::Build is not configured with C_support";
  3968.   $b->link(
  3969.     module_name => $module_name,
  3970.     objects     => [$spec->{obj_file}, @$objects],
  3971.     lib_file    => $spec->{lib_file},
  3972.     extra_linker_flags => $p->{extra_linker_flags} );
  3973.  
  3974.   return $spec->{lib_file};
  3975. }
  3976.  
  3977. sub compile_xs {
  3978.   my ($self, $file, %args) = @_;
  3979.   
  3980.   $self->log_info("$file -> $args{outfile}\n");
  3981.  
  3982.   if (eval {require ExtUtils::ParseXS; 1}) {
  3983.     
  3984.     ExtUtils::ParseXS::process_file(
  3985.                     filename => $file,
  3986.                     prototypes => 0,
  3987.                     output => $args{outfile},
  3988.                    );
  3989.   } else {
  3990.     # Ok, I give up.  Just use backticks.
  3991.     
  3992.     my $xsubpp = Module::Build::ModuleInfo->find_module_by_name('ExtUtils::xsubpp')
  3993.       or die "Can't find ExtUtils::xsubpp in INC (@INC)";
  3994.     
  3995.     my @typemaps;
  3996.     push @typemaps, Module::Build::ModuleInfo->find_module_by_name('ExtUtils::typemap', \@INC);
  3997.     my $lib_typemap = Module::Build::ModuleInfo->find_module_by_name('typemap', ['lib']);
  3998.     if (defined $lib_typemap and -e $lib_typemap) {
  3999.       push @typemaps, 'typemap';
  4000.     }
  4001.     @typemaps = map {+'-typemap', $_} @typemaps;
  4002.  
  4003.     my $cf = $self->{config};
  4004.     my $perl = $self->{properties}{perl};
  4005.     
  4006.     my @command = ($perl, "-I".$cf->get('installarchlib'), "-I".$cf->get('installprivlib'), $xsubpp, '-noprototypes',
  4007.            @typemaps, $file);
  4008.     
  4009.     $self->log_info("@command\n");
  4010.     my $fh = IO::File->new("> $args{outfile}") or die "Couldn't write $args{outfile}: $!";
  4011.     print {$fh} $self->_backticks(@command);
  4012.     close $fh;
  4013.   }
  4014. }
  4015.  
  4016. sub split_like_shell {
  4017.   my ($self, $string) = @_;
  4018.   
  4019.   return () unless defined($string);
  4020.   return @$string if UNIVERSAL::isa($string, 'ARRAY');
  4021.   $string =~ s/^\s+|\s+$//g;
  4022.   return () unless length($string);
  4023.   
  4024.   return Text::ParseWords::shellwords($string);
  4025. }
  4026.  
  4027. sub run_perl_script {
  4028.   my ($self, $script, $preargs, $postargs) = @_;
  4029.   foreach ($preargs, $postargs) {
  4030.     $_ = [ $self->split_like_shell($_) ] unless ref();
  4031.   }
  4032.   return $self->run_perl_command([@$preargs, $script, @$postargs]);
  4033. }
  4034.  
  4035. sub run_perl_command {
  4036.   # XXX Maybe we should accept @args instead of $args?  Must resolve
  4037.   # this before documenting.
  4038.   my ($self, $args) = @_;
  4039.   $args = [ $self->split_like_shell($args) ] unless ref($args);
  4040.   my $perl = ref($self) ? $self->perl : $self->find_perl_interpreter;
  4041.  
  4042.   # Make sure our local additions to @INC are propagated to the subprocess
  4043.   local $ENV{PERL5LIB} = join $self->config('path_sep'), $self->_added_to_INC;
  4044.  
  4045.   return $self->do_system($perl, @$args);
  4046. }
  4047.  
  4048. # Infer various data from the path of the input filename
  4049. # that is needed to create output files.
  4050. # The input filename is expected to be of the form:
  4051. #   lib/Module/Name.ext or Module/Name.ext
  4052. sub _infer_xs_spec {
  4053.   my $self = shift;
  4054.   my $file = shift;
  4055.  
  4056.   my $cf = $self->{config};
  4057.  
  4058.   my %spec;
  4059.  
  4060.   my( $v, $d, $f ) = File::Spec->splitpath( $file );
  4061.   my @d = File::Spec->splitdir( $d );
  4062.   (my $file_base = $f) =~ s/\.[^.]+$//i;
  4063.  
  4064.   $spec{base_name} = $file_base;
  4065.  
  4066.   $spec{src_dir} = File::Spec->catpath( $v, $d, '' );
  4067.  
  4068.   # the module name
  4069.   shift( @d ) while @d && ($d[0] eq 'lib' || $d[0] eq '');
  4070.   pop( @d ) while @d && $d[-1] eq '';
  4071.   $spec{module_name} = join( '::', (@d, $file_base) );
  4072.  
  4073.   $spec{archdir} = File::Spec->catdir($self->blib, 'arch', 'auto',
  4074.                       @d, $file_base);
  4075.  
  4076.   $spec{bs_file} = File::Spec->catfile($spec{archdir}, "${file_base}.bs");
  4077.  
  4078.   $spec{lib_file} = File::Spec->catfile($spec{archdir},
  4079.                     "${file_base}.".$cf->get('dlext'));
  4080.  
  4081.   $spec{c_file} = File::Spec->catfile( $spec{src_dir},
  4082.                        "${file_base}.c" );
  4083.  
  4084.   $spec{obj_file} = File::Spec->catfile( $spec{src_dir},
  4085.                      "${file_base}".$cf->get('obj_ext') );
  4086.  
  4087.   return \%spec;
  4088. }
  4089.  
  4090. sub process_xs {
  4091.   my ($self, $file) = @_;
  4092.  
  4093.   my $spec = $self->_infer_xs_spec($file);
  4094.  
  4095.   # File name, minus the suffix
  4096.   (my $file_base = $file) =~ s/\.[^.]+$//;
  4097.  
  4098.   # .xs -> .c
  4099.   $self->add_to_cleanup($spec->{c_file});
  4100.  
  4101.   unless ($self->up_to_date($file, $spec->{c_file})) {
  4102.     $self->compile_xs($file, outfile => $spec->{c_file});
  4103.   }
  4104.  
  4105.   # .c -> .o
  4106.   my $v = $self->dist_version;
  4107.   $self->compile_c($spec->{c_file},
  4108.            defines => {VERSION => qq{"$v"}, XS_VERSION => qq{"$v"}});
  4109.  
  4110.   # archdir
  4111.   File::Path::mkpath($spec->{archdir}, 0, oct(777)) unless -d $spec->{archdir};
  4112.  
  4113.   # .xs -> .bs
  4114.   $self->add_to_cleanup($spec->{bs_file});
  4115.   unless ($self->up_to_date($file, $spec->{bs_file})) {
  4116.     require ExtUtils::Mkbootstrap;
  4117.     $self->log_info("ExtUtils::Mkbootstrap::Mkbootstrap('$spec->{bs_file}')\n");
  4118.     ExtUtils::Mkbootstrap::Mkbootstrap($spec->{bs_file});  # Original had $BSLOADLIBS - what's that?
  4119.     {my $fh = IO::File->new(">> $spec->{bs_file}")}  # create
  4120.     utime((time)x2, $spec->{bs_file});  # touch
  4121.   }
  4122.  
  4123.   # .o -> .(a|bundle)
  4124.   $self->link_c($spec->{archdir}, $file_base);
  4125. }
  4126.  
  4127. sub do_system {
  4128.   my ($self, @cmd) = @_;
  4129.   $self->log_info("@cmd\n");
  4130.  
  4131.   # Some systems proliferate huge PERL5LIBs, try to ameliorate:
  4132.   my %seen;
  4133.   my $sep = $self->config('path_sep');
  4134.   local $ENV{PERL5LIB} = 
  4135.     ( !exists($ENV{PERL5LIB}) ? '' :
  4136.       length($ENV{PERL5LIB}) < 500
  4137.       ? $ENV{PERL5LIB}
  4138.       : join $sep, grep { ! $seen{$_}++ and -d $_ } split($sep, $ENV{PERL5LIB})
  4139.     );
  4140.  
  4141.   my $status = system(@cmd);
  4142.   if ($status and $! =~ /Argument list too long/i) {
  4143.     my $env_entries = '';
  4144.     foreach (sort keys %ENV) { $env_entries .= "$_=>".length($ENV{$_})."; " }
  4145.     warn "'Argument list' was 'too long', env lengths are $env_entries";
  4146.   }
  4147.   return !$status;
  4148. }
  4149.  
  4150. sub copy_if_modified {
  4151.   my $self = shift;
  4152.   my %args = (@_ > 3
  4153.           ? ( @_ )
  4154.           : ( from => shift, to_dir => shift, flatten => shift )
  4155.          );
  4156.   $args{verbose} = !$self->quiet
  4157.     unless exists $args{verbose};
  4158.   
  4159.   my $file = $args{from};
  4160.   unless (defined $file and length $file) {
  4161.     die "No 'from' parameter given to copy_if_modified";
  4162.   }
  4163.   
  4164.   my $to_path;
  4165.   if (defined $args{to} and length $args{to}) {
  4166.     $to_path = $args{to};
  4167.   } elsif (defined $args{to_dir} and length $args{to_dir}) {
  4168.     $to_path = File::Spec->catfile( $args{to_dir}, $args{flatten}
  4169.                     ? File::Basename::basename($file)
  4170.                     : $file );
  4171.   } else {
  4172.     die "No 'to' or 'to_dir' parameter given to copy_if_modified";
  4173.   }
  4174.   
  4175.   return if $self->up_to_date($file, $to_path); # Already fresh
  4176.  
  4177.   {
  4178.     local $self->{properties}{quiet} = 1;
  4179.     $self->delete_filetree($to_path); # delete destination if exists
  4180.   }
  4181.  
  4182.   # Create parent directories
  4183.   File::Path::mkpath(File::Basename::dirname($to_path), 0, oct(777));
  4184.   
  4185.   $self->log_info("Copying $file -> $to_path\n") if $args{verbose};
  4186.   
  4187.   if ($^O eq 'os2') {# copy will not overwrite; 0x1 = overwrite
  4188.     chmod 0666, $to_path;
  4189.     File::Copy::syscopy($file, $to_path, 0x1) or die "Can't copy('$file', '$to_path'): $!";
  4190.   } else {
  4191.     File::Copy::copy($file, $to_path) or die "Can't copy('$file', '$to_path'): $!";
  4192.   }
  4193.  
  4194.   # mode is read-only + (executable if source is executable)
  4195.   my $mode = oct(444) | ( $self->is_executable($file) ? oct(111) : 0 );
  4196.   chmod( $mode, $to_path );
  4197.  
  4198.   return $to_path;
  4199. }
  4200.  
  4201. sub up_to_date {
  4202.   my ($self, $source, $derived) = @_;
  4203.   $source  = [$source]  unless ref $source;
  4204.   $derived = [$derived] unless ref $derived;
  4205.  
  4206.   return 0 if grep {not -e} @$derived;
  4207.  
  4208.   my $most_recent_source = time / (24*60*60);
  4209.   foreach my $file (@$source) {
  4210.     unless (-e $file) {
  4211.       $self->log_warn("Can't find source file $file for up-to-date check");
  4212.       next;
  4213.     }
  4214.     $most_recent_source = -M _ if -M _ < $most_recent_source;
  4215.   }
  4216.   
  4217.   foreach my $derived (@$derived) {
  4218.     return 0 if -M $derived > $most_recent_source;
  4219.   }
  4220.   return 1;
  4221. }
  4222.  
  4223. sub dir_contains {
  4224.   my ($self, $first, $second) = @_;
  4225.   # File::Spec doesn't have an easy way to check whether one directory
  4226.   # is inside another, unfortunately.
  4227.   
  4228.   ($first, $second) = map File::Spec->canonpath($_), ($first, $second);
  4229.   my @first_dirs = File::Spec->splitdir($first);
  4230.   my @second_dirs = File::Spec->splitdir($second);
  4231.  
  4232.   return 0 if @second_dirs < @first_dirs;
  4233.   
  4234.   my $is_same = ( File::Spec->case_tolerant
  4235.           ? sub {lc(shift()) eq lc(shift())}
  4236.           : sub {shift() eq shift()} );
  4237.   
  4238.   while (@first_dirs) {
  4239.     return 0 unless $is_same->(shift @first_dirs, shift @second_dirs);
  4240.   }
  4241.   
  4242.   return 1;
  4243. }
  4244.  
  4245. 1;
  4246. __END__
  4247.  
  4248.  
  4249. =head1 NAME
  4250.  
  4251. Module::Build::Base - Default methods for Module::Build
  4252.  
  4253. =head1 SYNOPSIS
  4254.  
  4255.   Please see the Module::Build documentation.
  4256.  
  4257. =head1 DESCRIPTION
  4258.  
  4259. The C<Module::Build::Base> module defines the core functionality of
  4260. C<Module::Build>.  Its methods may be overridden by any of the
  4261. platform-dependent modules in the C<Module::Build::Platform::>
  4262. namespace, but the intention here is to make this base module as
  4263. platform-neutral as possible.  Nicely enough, Perl has several core
  4264. tools available in the C<File::> namespace for doing this, so the task
  4265. isn't very difficult.
  4266.  
  4267. Please see the C<Module::Build> documentation for more details.
  4268.  
  4269. =head1 AUTHOR
  4270.  
  4271. Ken Williams <kwilliams@cpan.org>
  4272.  
  4273. =head1 COPYRIGHT
  4274.  
  4275. Copyright (c) 2001-2006 Ken Williams.  All rights reserved.
  4276.  
  4277. This library is free software; you can redistribute it and/or
  4278. modify it under the same terms as Perl itself.
  4279.  
  4280. =head1 SEE ALSO
  4281.  
  4282. perl(1), Module::Build(3)
  4283.  
  4284. =cut
  4285.  
  4286. # vim:ts=8:sw=2:et:sta:sts=2
  4287.